许多刚刚接触gRPC用户或是刚刚把gRPC服务部署到kubernetes中感到惊讶的是,发现Kubernetes的默认负载均衡通常无法与gRPC一起使用。例如,当您使用一个简单的gRPC Node.js微服务应用程序并将其部署在Kubernetes上时,将发生以下情况:
尽管此处显示的服务具有多个Pod,但从Kubernetes的CPU图形可以清楚地看到,只有一个Pod实际上正在执行所有工作-因为只有一个Pod正在接收任何流量。为什么?
gRPC使用性能增强的HTTP/2协议。 HTTP/2具备更低的延迟的特点,其实是通过利用单个长期存在的TCP连接并在其上多路复用请求/响应。这会给第4层(L4)负载均衡器带来问题,因为它们的级别太低,无法根据接收到的流量类型做出路由决策。这样,尝试对HTTP/2流量进行负载均衡的L4负载均衡器将打开一个TCP连接,并将所有连续的流量路由到该相同的长期连接,从而实际上取消了负载均衡。
Kubernetes的kube-proxy本质上是一个L4负载均衡器,因此我们不能依靠它来均衡微服务之间的gRPC调用。
gRPC负载均衡方式
实际上gRPC负载均衡有以下两种实现方式:
- Proxy(代理负载均衡在某些文献中也称为服务器端负载均衡)
- Client side
在代理负载均衡与客户端负载均衡之间进行选择其实是结构的选择