做者最近用golang实现了一个TCP负载均衡器,灵感来自grpc。几个主要的特性就是:git
项目开源地址github
先介绍几种经常使用的负载均衡机制,如下几种负载均衡方案介绍来自grpc服务发现&负载均衡golang
根据负载均衡实现所在的位置不一样,一般可分为如下四种解决方案:算法
在服务消费者和服务提供者之间有一个独立的LB,一般是专门的硬件设备如 F5,或者基于软件如 LVS,HAproxy等实现。LB上有全部服务的地址映射表,一般由运维配置注册,当服务消费方调用某个目标服务时,它向LB发起请求,由LB以某种策略,好比轮询(Round-Robin)作负载均衡后将请求转发到目标服务。LB通常具有健康检查能力,能自动摘除不健康的服务实例。 该方案主要问题:后端
单点问题,全部服务调用流量都通过LB,当服务数量和调用量大的时候,LB容易成为瓶颈,且一旦LB发生故障影响整个系统;
服务消费方、提供方之间增长了一级,有必定性能开销。浏览器
针对第一个方案的不足,此方案将LB的功能集成到服务消费方进程里,也被称为软负载或者客户端负载方案。服务提供方启动时,首先将服务地址注册到服务注册表,同时按期报心跳到服务注册表以代表服务的存活状态,至关于健康检查,服务消费方要访问某个服务时,它经过内置的LB组件向服务注册表查询,同时缓存并按期刷新目标服务地址列表,而后以某种负载均衡策略选择一个目标服务地址,最后向目标服务发起请求。LB和服务发现能力被分散到每个服务消费者的进程内部,同时服务消费方和服务提供方之间是直接调用,没有额外开销,性能比较好。该方案主要问题:缓存
开发成本,该方案将服务调用方集成到客户端的进程里头,若是有多种不一样的语言栈,就要配合开发多种不一样的客户端,有必定的研发和维护成本;
另外生产环境中,后续若是要对客户库进行升级,势必要求服务调用方修改代码并从新发布,升级较复杂。服务器
该方案是针对第二种方案的不足而提出的一种折中方案,原理和第二种方案基本相似。
不一样之处是将LB和服务发现功能从进程内移出来,变成主机上的一个独立进程。主机上的一个或者多个服务要访问目标服务时,他们都经过同一主机上的独立LB进程作服务发现和负载均衡。该方案也是一种分布式方案没有单点问题,一个LB进程挂了只影响该主机上的服务调用方,服务调用方和LB之间是进程内调用性能好,同时该方案还简化了服务调用方,不须要为不一样语言开发客户库,LB的升级不须要服务调用方改代码。
该方案主要问题:部署较复杂,环节多,出错调试排查问题不方便。网络
gRPC开源组件官方并未直接提供服务注册与发现的功能实现,但其设计文档已提供实现的思路,并在不一样语言的gRPC代码API中已提供了命名解析和负载均衡接口供扩展。并发
其基本实现原理:
服务启动后gRPC客户端向命名服务器发出名称解析请求,名称将解析为一个或多个IP地址,每一个IP地址标示它是服务器地址仍是负载均衡器地址,以及标示要使用那个客户端负载均衡策略或服务配置。
客户端实例化负载均衡策略,若是解析返回的地址是负载均衡器地址,则客户端将使用grpclb策略,不然客户端使用服务配置请求的负载均衡策略。
负载均衡策略为每一个服务器地址建立一个子通道(channel)。
当有rpc请求时,负载均衡策略决定那个子通道即grpc服务器将接收请求,当可用服务器为空时客户端的请求将被阻塞。
能够看到第一种负载均衡是在server端进行负载均衡(也叫Proxy负载均衡),第二种和第三种负载均衡方案都是在客户端进行的负载均衡,这两类负载均衡各有优缺点
grpc负载均衡是上述两种负载均衡机制的结合体,经过添加一个额外的load balancer server来实现,它基本上避免了两种负载均衡机制的缺点。
为何要实现一个负载均衡器,由于目前为止没有找到知足做者要求的负载均衡器。市面上负载均衡器大可能是proxy负载均衡器,像LVS,Haproxy,上行流量会成为它们的瓶颈。grpc的负载均衡只是作了设计,并无实现,而且grpc负载均衡设计的初衷是per-call的,设计的目标应该是针对微服务中的API调用,而且感受grpc负载均衡设计还有改进的空间。
gobalan有一下特色:
整个系统的交互流程是下面这个样子:
关于gobalan的更加详细的设计原理和使用方法,参考项目地址