负载均衡分类(服务端)
常见的负载均衡系统包括 3 种:DNS 负载均衡、硬件负载均衡和软件负载均衡。
DNS 负载均衡
DNS 是最简单也是最常见的负载均衡方式,一般用来实现地理级别的均衡。例如,北方的用户访问北京的机房,南方的用户访问深圳的机房。DNS 负载均衡的本质是 DNS 解析同一个域名可以返回不同的IP地址。例如,同样是 www.baidu.com ,北方用户解析后获取的地址是 61.135.165.224(这是北京机房的 IP),南方用户解析后获取的地址是 14.215.177.38(这是深圳机房的 IP)。
- 优点
- 简单与低成本:负载均衡工作交给 DNS 服务器处理,无须自己开发或者维护负载均衡设备。
- 就近访问,速度快:DNS 解析时可以根据请求来源 IP,解析成距离用户最近的服务器地址,可以加快访问速度,改善性能。
- 缺点
- 更新不及时:DNS 缓存的时间比较长,修改 DNS 配置后,由于缓存的原因,还是有很多用户会继续访问修改前的 IP,这样的访问会失败,达不到负载均衡的目的,并且也影响用户正常使用业务。根据经验,正常域名修改后全国 DNS 缓存需要 48 小时,才能大部分更新完毕,而刷全世界缓存需要 72 小时。
- 扩展性差:DNS 负载均衡的控制权在域名商那里,无法根据业务特点针对其做更多的定制化功能和扩展特性。
- 分配策略比较简单:DNS 负载均衡支持的算法少;不能区分服务器的差异(不能根据系统与服务的状态来判断负载);也无法感知后端服务器的状态。
硬件负载均衡
- Info
- 单独的硬件来实现,与路由器、交换机类似,可以理解为一个用于负载均衡的基础网络设备。
- 业界典型设备:F5 和 A10。性能高、功能强大,但是价格不便宜。
- 普通业务量级的公司一是负担不起,二是业务量没那么大,用这些设备也是浪费。
- 优点
- 功能强大:全面支持各层级的负载均衡,支持全面的负载均衡算法,支持全局负载均衡。
- 性能强大:对比一下,软件负载均衡支持到 10 万级并发已经很厉害了,硬件负载均衡可以支持 100 万以上的并发。
- 稳定性高:商用硬件负载均衡,经过了良好的严格测试,经过大规模使用,稳定性高。
- 支持安全防护:硬件均衡设备除具备负载均衡功能外,还具备防火墙、防 DDoS 攻击等安全功能。
- 缺点
- 价格昂贵:最普通的一台 F5 就是一台“马 6”,好一点的就是“Q7”了。
- 扩展能力差:硬件设备,可以根据业务进行配置,但无法进行扩展和定制。
软件负载均衡
- Info
- 通过负载均衡软件来实现负载均衡功能。
- 常见的有 Nginx 和 LVS(Linux Virtual Server 虚拟服务器)
- Nginx 是软件的 7 层负载均衡,LVS 是 Linux 内核的 4 层负载均衡。
- 七层负载均衡工作在应用层,主要协议是 HTTP,会读取报文的数据部分(比如说我们的 HTTP 部分的报文),然后根据读取到的数据内容(如 URL、Cookie)做出负载均衡决策。
- 四层负载均衡工作在传输层,主要协议是 TCP/UDP,能看到 IP+端口号。根据 IP 和端口号来判断转发情况,执行网络地址转换(NAT)来向上游服务器转发网络数据包。由于不涉及具体报文内容,因此在应用层角度,可以适用于任何应用。
- 软硬件最大区别就是性能,硬件负载均衡性能远远高于软件负载均衡性能。
- 优点
- 简单:无论是部署还是维护都比较简单。
- 便宜:只要买个 Linux 服务器,装上软件即可。
- 灵活:4 层和 7 层负载均衡可以根据业务进行选择;也可以根据业务进行比较方便的扩展,例如,可以通过 Nginx 的插件来实现业务的定制化功能。
- 缺点(相较于硬件的)
- 性能一般:一个 Nginx 大约能支撑 5 万并发。
- 功能没有硬件负载均衡那么强大。
- 一般不具备防火墙和防 DDoS 攻击等安全功能。
典型架构
- DNS 负载均衡用于实现地理级别的负载均衡;
- 硬件负载均衡用于实现集群级别的负载均衡;
- 软件负载均衡用于实现机器级别的负载均衡。

负载均衡(客户端)
客户端负载均衡 主要应用于系统内部的不同的服务之间,可以使用现成的负载均衡组件来实现。
在客户端负载均衡中,客户端会自己维护一份服务器的地址列表,发送请求之前,客户端会根据对应的负载均衡算法来选择具体某一台服务器处理请求。
客户端负载均衡器和服务运行在同一个进程或者说 Java 程序里,不存在额外的网络开销。不过,客户端负载均衡的实现会受到编程语言的限制,比如说 Spring Cloud Load Balancer 就只能用于 Java 语言。
Dubbo、Spring Cloud 等都内置了开箱即用的客户端负载均衡实现。Dubbo 属于是默认自带了负载均衡功能,Spring Cloud 是通过组件的形式实现的负载均衡,属于可选项。
Java 生态流行的负载均衡组件
Netflix Ribbon 和 Spring Cloud Load Balancer 就是目前 Java 生态最流行的两个负载均衡组件。Ribbon 是老牌负载均衡组件,由 Netflix 开发,功能比较全面,支持的负载均衡策略也比较多。 Spring Cloud Load Balancer 是 Spring 官方为了取代 Ribbon 而推出的,功能相对更简单一些,支持的负载均衡也少一些。
Ribbon 支持的 7 种负载均衡策略:
RandomRule:随机策略。RoundRobinRule(默认):轮询策略WeightedResponseTimeRule:权重(根据响应时间决定权重)策略BestAvailableRule:最小连接数策略RetryRule:重试策略(按照轮询策略来获取服务,如果获取的服务实例为 null 或已经失效,则在指定的时间之内不断地进行重试来获取服务,如果超过指定时间依然没获取到服务实例则返回 null)AvailabilityFilteringRule:可用敏感性策略(先过滤掉非健康的服务实例,然后再选择连接数较小的服务实例)ZoneAvoidanceRule:区域敏感性策略(根据服务所在区域的性能和服务的可用性来选择服务实例)
Spring Cloud Load Balancer 支持的 2 种负载均衡策略:
RandomLoadBalancer:随机策略RoundRobinLoadBalancer(默认):轮询策略
Spring Cloud Load Balancer 支持的负载均衡策略其实不止这两种,ServiceInstanceListSupplier 的实现类同样可以让其支持类似于 Ribbon 的负载均衡策略。这个应该是后续慢慢完善引入的,不看官方文档还真发现不了,所以说阅读官方文档真的很重要!
这里举两个官方的例子:
ZonePreferenceServiceInstanceListSupplier:实现基于区域的负载平衡HintBasedServiceInstanceListSupplier:实现基于 hint 提示的负载均衡
关于 Spring Cloud Load Balancer 更详细更新的介绍,推荐大家看看官方文档:https://docs.spring.io/spring-cloud-commons/docs/current/reference/html/#spring-cloud-loadbalancer ,一切以官方文档为主。
负载均衡算法
- 随机法
- 即使是随机的,但是概率问题存在部分机器在短时间内不被使用。
- 轮询法
- 挨个轮询服务器处理,也可以设置权重。
- 平滑的加权轮训算法
- 在加权轮询的基础上进一步改进的算法。最早是在 Nginx 中被实现,可以参考这个 commit。Dubbo 的加权轮询就借鉴了该算法实现并进一步做了优化。
- 两次随机法
- 随机两次,在两台服务器之间根据负载等情况选择最合适的服务器。
- 两次随机法的好处是可以动态地调节后端节点的负载,使其更加均衡。如果只使用一次随机法,可能会导致某些服务器过载,而某些服务器空闲。
- 哈希法
- 根据 IP、用户等请求进行哈希。
- 一致性哈希法
- 在服务器数目发生变更的时候,相同的请求在“哈希法”下会落在不同的服务器上。
- 一致性哈希算法的核心思想是将数据和节点都映射到一个哈希环上,然后根据哈希值的顺序来确定数据属于哪个节点。服务器数目变动后,只影响该服务器的哈希,而不会导致整个服务集群的哈希键值重新分布。
- 最小连接法
- 连接数最小的一台服务器来响应当前请求。
- 但是实际情况下,连接数少的服务器并不代表真实的负载情况,有的连接消耗资源多,有的少。
- 最少活跃法
- 最少活跃法以活动连接数为标准,活动连接数可以理解为当前正在处理的请求数。活跃数越低,说明处理能力越强,这样就可以使处理能力强的服务器处理更多请求。相同活跃数的情况下,可以进行加权随机。
- 最快响应时间法
- 以响应时间为标准来选择具体是哪一台服务器处理。客户端会维持每个服务器的响应时间,每次请求挑选响应时间最短的。相同响应时间的情况下,可以进行加权随机。
- 这种算法可以使得请求被更快处理,但可能会造成流量过于集中于高性能服务器的问题。
- 负载最低优先
- LVS 在第 4 层,可以以“连接数”来判断服务器的状态,服务器连接数越大,表明服务器压力越大。
- Nginx 在第 7 层,可以以“HTTP 请求数”来判断服务器状态(内置不支持,需扩展)。
- 可以根据业务特点来选择指标衡量系统压力。如果是 CPU 密集型,可以以“CPU 负载”来衡量系统压力;如果是 I/O 密集型,可以以“I/O 负载”来衡量系统压力。
- “CPU 负载最低优先的算法”需要收集服务器的负载情况,同时需要选择合适的“周期”。一分钟的负载标准,还是十五分钟的负载标准。
- 性能最优类
- 站在客户端的角度来进行分配的,优先将任务分配给处理速度最快的服务器,通过这种方式达到最快响应客户端的目的。
- 同样具有和“负载最低优先”相同的复杂度
- 收集数据需要耗费性能
- 所有的数据是全部使用还是通过采样来判断服务器情况
- 选择合适的周期
其他问题
有个问题想请教老师,进出的流量是不是都要通过负载均衡的那台机器。比如 a 是 NGINX 负载均衡服务器,bcd 是具体的机器,http 请求时是不是所有的 input 和 output 都经过负载均衡返回给客户端?
作者回复: nginx 的反向代理是这样的,但是 LVS 做负载均衡的时候,返回的流量可以不经过 LVS,具体你可以查查 LVS 的 TUN 和 DR 模式
参考链接
- 20 | 高性能负载均衡:分类及架构-从0开始学架构-极客时间
- 21 | 高性能负载均衡:算法-从0开始学架构-极客时间
- “高并发系统实战课 Mapping ” 负载均衡:19|流量调度:DNS、全站加速及机房负载均衡 - 极客时间已完结课程限时免费阅读 还没看
来源与延伸阅读(还没看):