前言
前段时间写过一篇 gRPC
的入门文章,在最后还留了一个坑没有填:也就是
gRPC
的负载均衡问题,因为当时的业务请求量不算大,再加上公司没有对 Istio 这类服务网格比较熟悉的大牛,所以我们也就一直拖着没有解决,依然只是使用了 kubernetes 的 service 进行负载,好在也没有出什么问题。
由于现在换了公司后也需要维护公司的服务网格服务,结合公司内部对 Istio 的使用现在终于不再停留在理论阶段了。
所以也终有机会将这个坑填了。
gRPC 负载均衡
负载不均衡
原理
先来回顾下背景,为什么会有 gRPC
负债不均衡的问题。由于 gRPC
是基于 HTTP/2 协议的,所以客户端和服务端会保持长链接,一旦链接建立成功后就会一直使用这个连接处理后续的请求。

除非我们每次请求之后都新建一个连接,这显然是不合理的。
所以要解决 gRPC
的负载均衡通常有两种方案:
服务端负载均衡
客户端负载均衡 在
gRPC
这个场景服务端负载均衡不是很合适,所有的请求都需要经过一个负载均衡器,这样它就成为整个系统的瓶颈,所以更推荐使用客户端负载均衡。
客户端负载均衡目前也有两种方案,最常见也是传统方案。这里以 Dubbo 的调用过程为例,调用的时候需要从服务注册中心获取到提供者的节点信息,然后在客户端本地根据一定的负载均衡算法得出一个节点然后发起请求。
换成 gRPC
也是类似的,这里以 go-zero
负载均衡的原理为例:
gRPC 官方库也提供了对应的负载均衡接口,但我们依然需要自己维护服务列表然后在客户端编写负载均衡算法,这里有个官方 demo:
https://github.com/grpc/grpc-go/blob/87eb5b7502493f758e76c4d09430c0049a81a557/examples/features/load_balancing/client/main.go
但切换到 kubernetes 环境中时再使用以上的方式就不够优雅了,因为我们使用 kubernetes 的目的就是不想再额外的维护这个客户端包,这部分能力最好是由 kubernetes 自己就能提供。
但遗憾的是 kubernetes 提供的 service 只是基于 L4 的负载,所以我们每次请求的时候都只能将请求发往同