原文地址:https://github.com/grpc/grpc/blob/master/doc/load-balancing.mdhtml
本文档解释了gPRC的负载均衡的设计。git
值得注意的是gRPC的负载均衡是发生在每次调用的基础上,而不是每条链接的基础上。换言之,即便全部请求都来自于同一个客户端,咱们仍旧想要它们被负载到全部的服务器上。github
在gPRC的负载均衡以前,先研究一下一些常见的负载均衡方式。算法
代理提供一个可靠的能够上报负载状况到负载均衡系统的客户端,由于代理会暂时的保留RPC请求和响应的副本,因此一般它们须要更多的资源。这个模式也增长了PRC的延迟。编程
在考虑到请求压力较重的服务,例如存储服务,代理模式被认为是效率低下的。后端
这个更厚的客户端将更多的负载均衡逻辑放在客户端。例如,客户端会包含许多负载均衡策略(轮询调度,随机调度等)用于在一个列表中选择服务。这个模式下,一个由名称解析系统或外部的负载均衡器等提供的服务器的列表会被静态的配置在客户端,这种状况下,客户端负责从列表中选择最佳的服务器。安全
这个方法的其中一个缺点是须要编写和维护包含多种编程语言或版本的负载均衡策略的客户端。那些策略可能会很是的复杂。一些算法须要客户端与服务端的交互,因此客户端可能须要变得更厚来提供额外的RPC用来健康检查或从用户发送的RPC请求中获取额外的负载信息。服务器
它也会使客户端的代码变得复杂:新的设计要隐藏多层负载均衡的复杂性使之就像是一个对于客户端的简单的服务端列表。架构
客户端负载均衡代码保持简单且可移植,实现了众所周知的算法(例如:轮询调度)用于选择服务。负载均衡器提供更复杂的负载均衡算法。客户端依赖于负载均衡器提供负载均衡配置以及一个客户端要发送请求到的服务器列表。当服务不可用或健康问题出现时,均衡器会更新须要均衡负载的服务器列表。负载均衡器会作出任何复杂的必须的决定并通知客户端。负载均衡器会和后端的服务器交互来收集负载和健康信息。负载均衡
gRPC客户端负载均衡代码必须简单且可移植的。客户端应该只包含简单的算法(例如:轮询调度)来选择服务器。对于复杂的算法,客户端应该依赖于一个负载均衡器来提供负载均衡配置和一个客户端应该发送请求到的服务器列表。当服务不可用或健康问题出现时,均衡器会更新须要均衡负载的服务器列表。负载均衡器会作出任何复杂且必须的决定并通知客户端。负载均衡器会和后端的服务器交互来收集负载和健康信息。
负载均衡器会和后台服务分开且一个折衷的负载均衡器会致使负载均衡器的负载均衡功能受到损害。换言之,一个折衷的的负载均衡器不该该致使客户端信任一个(多是恶意的)后端服务器,而不是在没有负载均衡的状况下。
gRPC主要的负载均衡机制是外部负载均衡器,一个外部的负载均衡器提供简单的客户端和一个最新的服务器列表。
gPRC客户端提供一个API来支持内置的负载均衡策略,然而,只有不多数(其中一个是grpclb策略实现了一个外部负载均衡器),而且不鼓励用户尝试添加更多的来扩展gRPC。相反的,新的负载均衡策略应该实如今外部的负载均衡器上。
在名称解析和服务器连接中,负载均衡策略适合gPRC客户端工做流。如下是它如何工做的:
1. 启动时,gPRC客户端经过服务名发起一个名称解析请求。名称会被解析为一个或更多的IP地址,每一个地址指明它是一个服务器地址或一个负载均衡器地址,而且包含一个服务配置指明那一个客户端的负载均衡策略应该被使用(例如: 轮询调度或grpclb)。
2. 客户端实现一个负载均衡策略。
3. 负载均衡策略对每个服务器地址建立一个子通道。
4. 对于每一个PRC发送请求,负载均衡策略决定应该发送到哪一个子通道(例如: 哪一个服务器)。