vlambda博客
学习文章列表

云原生微服务 gRPC 如何实现负载均衡

(给Go开发大全加星标)

来源:iyacontrol

https://zhuanlan.zhihu.com/p/336676373

【导读】云原生微服务的gRPC服务如何实现负载均衡?本文对常见4种方案做了详细介绍。

对于应用程序开发人员来说,gRPC是一种越来越普遍的选择。与诸如JSON-over-HTTP之类的替代协议相比,gRPC可以提供一些显着的好处,包括大幅降低(反序列化)成本,自动类型检查,格式化的API和更少的TCP管理开销。

但是gRPC建立在HTTP/2之上,并且HTTP/2设计为具有单个长期TCP连接,所有请求都在该TCP连接上进行多路复用(多个请求可以在同一时间在同一连接上处于活动状态)。但是这也意味着 gRPC 需要特殊的 load balancing。

本文主要介绍4种解决方案实现部署在Kubernetes中的gRPC服务的load balancing。

1)客户端lb + Name Resolver + Headless Service

该解决方案实现的是客户端负载均衡。实现gRPC客户端负载平衡需要两个主要组件: name resolver 和 load balancing policy。

云原生微服务 gRPC 如何实现负载均衡

默认gRPC 使用 dns 作为其 resolver。所以我们需要为我们的应用创建Headless Service 。关于Headless Service,我们这里不作详细介绍,大家可以参阅官方文档。创建 Headless Service 的服务,Kubernetes将在该服务的DNS条目中创建多个A记录,而每个A记录与之对应的是一个Pod IP。

2)集中式Proxy

通过集中式的代理来解决gRPC 负载均衡也是一种流行的解决方案。比如当我们的客户端处于公网,我们出于安全的考量,不可能将 server 配置为公网可访问,此时集中式LB就非常适合这种场景。

云原生微服务 gRPC 如何实现负载均衡

而如果我们的服务是部署在 kubernetes 中,那么选择一个支持gRPC的Ingress Controller 就可以完美解决问题。

目前基于 Envoy 实现的 Ingress Controller 均支持gRPC的负载均衡。比如 Contour,Ambassador, Gloo等。Envoy 是一个开源应用层(第 7 层)代理,提供许多高级特性。可以可以使用它来终止 SSL/TLS 连接并将 gRPC 流量路由到适当的 Kubernetes 服务。

比如我们在生产环境就是使用Contour来解决gRPC 服务负载均衡的问题。

云原生微服务 gRPC 如何实现负载均衡

而如果你恰好运行在Aws上,那么你可以选择ALB ingress Controller。

该方案优势是客户端无需复杂的配置,而 ingress 又是 kubernetes 本身的概念,没有其他概念的引入。

3)Service Mesh

目前所有的Service Mesh 解决方案都支持gRPC服务。包括Istio等以Envoy作为数据面的 Mesh 解决方案和 Linkerd 等非Envoy作为数据面的Mesh。

Mesh方案本质上依旧是Proxy。和集中式Proxy对比,只是将Proxy下沉到每个Client,以Sidecar的形式存在。

云原生微服务 gRPC 如何实现负载均衡

该方案比较复杂,不过Mesh解决方案是一个完整的服务治理方案,可以实现除了负载均衡之外的其他功能,比如故障注入,限流,熔断等,而且具备丰富的可观察性和扩展性,以及一个零信任的网络。如果你恰好在生产环境落地了Mesh,那么该方案是你最佳的选择。

4)无代理 xds 负载均衡

xDS 本身是Envoy中的概念,现在已经发展为用于配置各种数据平面软件的标准。最新版本的gRPC已经支持 基于xDS的负载平衡,目前为止,gRPC团队增加了对C-core,Java和Go语言的支持。

在xDS API流程中,客户端使用以下主要API:

  • Listener Discovery Service (LDS): 返回监听器资源。基本上用作gRPC客户端配置的root。指向RouteConfiguration。
  • Route Discovery Service (RDS): 返回RouteConfiguration资源。提供用于填充gRPC服务配置的数据。指向集群。
  • Cluster Discovery Service (CDS): 返回集群资源。配置诸如负载平衡策略和负载报告之类的内容。指向ClusterLoadAssignment。
  • Endpoint Discovery Service (EDS): 返回ClusterLoadAssignment资源。配置一组端点(后端服务器)以实现负载均衡,并可能告诉客户端丢弃请求。
云原生微服务 gRPC 如何实现负载均衡

为了利用xDS负载均衡,gRPC客户端需要连接到xDS服务器。客户端需要在用于创建gRPC通道的目标URI中使用xds解析器。下图显示了API调用的顺序。

云原生微服务 gRPC 如何实现负载均衡

xDS服务器负责发现gRPC服务器的端点并将其传达给客户端。然后,客户端会定期请求更新。

我们使用 Envoy go-control-plane库来实现xDS server。对于部署在Kubernetes中的gRPC的服务,我们可以使用k8s client-go来发现目标EndPoints。

相对于 客户端lb + Name Resolver + Headless Service,目前xds 负载均衡支持的语言不够丰富,这是我们选择该方案时,不得不考虑的问题。

这是一种无proxy的客户端负载均衡方案。对比Mesh方案,性能更好。但是该方案初衷是作为Service Mesh 方案的一种补充,并不是用来替换Mesh。

在以下的场景中,你可以考虑使用无Proxy的方案:

  • 高性能 gRPC 应用,你不想承担引入Sidecar带来的延迟。
  • 无法部署 Sidecar 代理的环境
  • 异构服务网格


 - EOF -

推荐阅读(点击标题可打开)

1、

2、

3、


Go 开发大全

参与维护一个非常全面的Go开源技术资源库。日常分享 Go, 云原生、k8s、Docker和微服务方面的技术文章和行业动态。

关注后获取

回复 Go 获取6万star的Go资源库



分享、点赞和在看

支持我们分享更多好文章,谢谢!