grpc 服务注册发现 与 负载均衡 话题

866 阅读1分钟
  1. 客户端程序只需要在程序初始化时通过 grpc.Dial("xxx") 在全局可见的范围内创建一次 ClientConns(多个不同服务的ClientConn),不需要每次调用 grpc 服务时都去创建 ClientConn,HTTP/2 虽然是长连接,但是每次调用都是无状态的,不同的 goroutine 共用一个 ClientConn 去调用服务,可以充分利用 HTTP/2 多路复用的特性。另外,grpc 会自己维护 ClientConn,不需要额外地管理断线重连等问题。总结下来就是,1、不需要创建连接池,因为有多路复用 2、不需要处理断线重连。

参考连接:

  1. grpc 的负载均衡有两个场景,一个是通过服务注册中心,另外一个是利用 k8s 的service dns。

服务注册中心的场景下,可以通过 grpc 的 DialOption 来实现, 伪代码 grpc.Dial("srvName", grpc.WithBalancer(grpc.RoundRobin(resolver)))。原理是 resolver 从服务注册中心获取到 srvName 的多个通讯地址,分别对这些服务进行连接(Dial 方法返回的 ClientConn 代表的是多个实际连接),然后以 RoundRobin 的策略往不同的连接上发请求。

在 k8s 场景下,如果直接通过 grpc.Dial("k8s service name")的方式去创建 ClientConn,k8s 只会选取 service 后端 pods 中的一个进行连接,以后每次往这条 ClientConn 上发请求,都只会发往一个 pod。第一种实现方式是,每次调用服务时都去创建 ClientConn 并且 defer Close,这种方式的缺点是每次握手产生耗时和资源浪费,而且违背了多路复用的最佳实践。另外一种方式是自己实现resolver,获取service后端pods的地址,同第一个场景。

参考链接: