分布式系统常见负载均衡实现模式
- [1. 4层负载均衡](#1. 4层负载均衡)
-
- [1.1. 负载均衡的常见需求](#1.1. 负载均衡的常见需求)
- [1.2. 负载均衡的实现模式](#1.2. 负载均衡的实现模式)
-
- [1.2.1 DR模式](#1.2.1 DR模式)
- [1.2.2 TUN模式](#1.2.2 TUN模式)
- [1.2.3 NAT模式](#1.2.3 NAT模式)
- [1.2.4 FULLNAT模式](#1.2.4 FULLNAT模式)
- [1.2.5 4种模式的差异](#1.2.5 4种模式的差异)
- [1.3. 负载均衡的均衡算法](#1.3. 负载均衡的均衡算法)
-
- [1.3.1 静态负载均衡](#1.3.1 静态负载均衡)
- [1.3.2 轮询法](#1.3.2 轮询法)
- [1.3.3 加权循环法](#1.3.3 加权循环法)
- [1.3.4 IP 哈希法](#1.3.4 IP 哈希法)
- [1.3.5 动态负载均衡](#1.3.5 动态负载均衡)
- [1.3.6 最少连接法](#1.3.6 最少连接法)
- [1.3.7 加权最小连接法](#1.3.7 加权最小连接法)
- [1.3.8 最短响应时间法](#1.3.8 最短响应时间法)
- [1.3.9 基于资源的方法](#1.3.9 基于资源的方法)
- [1.4. 健康检查](#1.4. 健康检查)
-
- [1.4.1 基于心跳检测](#1.4.1 基于心跳检测)
- [1.4.2 基于端口检测](#1.4.2 基于端口检测)
- [1.4.3 基于HTTP请求检测](#1.4.3 基于HTTP请求检测)
- [1.4.4 基于TCP检测](#1.4.4 基于TCP检测)
- [1.4.5 基于DNS检测](#1.4.5 基于DNS检测)
- [2. 7层负载均衡](#2. 7层负载均衡)
-
- [2.1 域名uri转发配置](#2.1 域名uri转发配置)
- [2.2 获取客户端ip](#2.2 获取客户端ip)
- [3. 常见的负载均衡产品](#3. 常见的负载均衡产品)
-
- 3.1lvs
- [3.3 keepalive](#3.3 keepalive)
- [3.4 nginx](#3.4 nginx)
- [4. 疑问和思考](#4. 疑问和思考)
-
- 4.1该如何设计负载均衡产品能够满足各类需求?
- [4.2 udp协议如何做健康检查?](#4.2 udp协议如何做健康检查?)
- [5. 参考文档](#5. 参考文档)
负载均衡是指将网络流量分发到不同的服务器上,以实现资源的均衡利用和提高系统的性能、可靠性和可扩展性。本文整理负载均衡常见的需求以及设计模式,便于后续读者更好的理解负载均衡的相关原理。
1. 4层负载均衡
1.1. 负载均衡的常见需求
通常在设计负载均衡产品时,需要考虑应用对于负载均衡的相关需求,通常的需求主要是
- 高可用性:当一个服务器发生故障时,能够自动将流量转移到其他可用的服务器上,保证用户的访问不受影响。
- 均衡负载:将流量均匀地分发到不同的服务器上,避免某一台服务器过载,从而提高整个系统的性能。
- 会话保持:将同一个用户的请求始终转发到同一台服务器上,以保持用户的会话状态,避免应用程序中断。
- 动态调整:根据服务器的负载情况自动调整负载均衡策略,以适应不同的流量情况和服务器的性能变化。
- 安全性:能够识别和阻止恶意流量,保护服务器免受攻击,如DDoS攻击。
- 可扩展性:能够随着流量的增加动态地添加更多的服务器,以应对系统的扩展需求。
- 监控和统计:提供对负载均衡器和服务器的性能和运行情况的监控和统计功能,以便于管理和故障排除。
- 支持不同的应用协议:能够支持HTTP、HTTPS、TCP、UDP等多种应用协议的负载均衡。
- 支持不同的负载均衡算法:能够根据实际需求选择合适的负载均衡算法,如轮询、加权轮询、最少连接等。
- 高性能:能够处理大量的网络流量,并提供快速的数据转发和响应时间。
- 健康检查:能够检测后端rs,如果后端rs异常能够及时剔除异常的rs,避免流量转发到异常的rs上,从而导致业务异常
- 后端rs获取客户端ip:部分后端rs在希望获取客户端的ip便于进行业务逻辑运算
1.2. 负载均衡的实现模式
通常负载均衡器有多种实现方式,但是不通的实现方式会有对应的优劣。本文以lvs为例,梳理常见的负载均衡器的实现协议,并梳理对应的优劣。
1.2.1 DR模式
链路过程
- CIP--VIP,客户端发送请求到LVS负载均衡服务器(虚拟IP,master节点)
- 到达LVS负载均衡服务器后,在网络内核中,进行四表五链路由处理
- 进入PREROUTING链,进入路由处理前,进行判断,发现VIP是本机IP,转向INPUT链
- 进入INPUT链,IP<CIP,VIP>不动,将SRC-MAC从<CIP-MAC,DIP-MAC>,改成<VIP-MAC,RIP-MAC>,转向POSTROUTING链
- 进入POSTROUTING链,进行路由后处理,因为DS和RS在同一个网络中,所以是通过二层转发,通过MAC将请求发送至RS真实服务器。
- RS发现请求报文的MAC地址是自己的MAC地址,就接收此报文。真实服务器处理完请求后,将响应报文,IP<VIP,CIP>,将响应报文通过lo接口传送给eth0网卡然后向外发出,直接返回达客户端,而不经过VIP
DR模型特性
- 保证前端路由将目标地址为VIP报文统统发给Director Server,而不是RS
- Director Server服务器处理的是请求,响应由RS服务器直接发送给客户端
- arptables:在arp的层次上实现在ARP解析时做防火墙规则,过滤RS响应ARP请求。这是由iptables提供的
- 修改RS上内核参数(arp_ignore和arp_announce)将RS上的VIP配置在lo接口的别名上,并限制其不能响应对VIP地址解析请求(最容易实现)
- RS可以使用私有地址;也可以是公网地址,如果使用公网地址,此时可以通过互联网对RIP进行直接访问
- RS跟Director Server必须在同一个物理网络中
- 所有的请求报文经由Director Server,但响应报文必须不能经过Director Server
- 不支持地址转换,也不支持端口映射 (工作在数据链路层)
- RS的网关绝不允许指向DIP(因为我们不允许他经过director)
- RS上的lo接口配置VIP的IP地址
模式缺陷
- RS和DS必须在同一机房中,该模式是在数据链路层做的MAC修改,需要在同一个物理机房中,进行二层数据转发。
使用场景
- 全称为Direct Routing 直接路由,建议大规模使用,也是现在较多使用场景的方法
1.2.2 TUN模式
链路过程
CIP--VIP,客户端发送请求到LVS负载均衡服务器(虚拟IP,master节点)
- 到达LVS负载均衡服务器后,在网络内核中,进行四表五链路由处理
- 进入PREROUTING链,进入路由处理前,进行判断,发现VIP是本机IP,转向INPUT链
- 进入INPUT链,在请求报文外,在封一层包,源IP为为DIP,目标IP为RIP,转向POSTROUTING
- POSTROUTING链根据最新封装的IP报文,发向RS
- RS接收到报文后发现是自己的IP地址,就将报文接收下来,拆除掉最外层的IP后,会发现里面还有一层IP首部,而且目标是自己的lo接口VIP,那么此时RS开始处理此请求,处理完成之后,通过lo接口送给eth0网卡,然后向外传递。此时的源IP地址为VIP,目标IP为CIP。
LVS动作
- 在原有的IP报文外再次封装多一层IP首部,内部IP首部(源地址为CIP,目标IP为VIP),外层IP首部(源地址为DIP,目标IP为RIP)
TUN模型特性
- RIP、VIP、DIP全是公网地址
- RS的网关不会也不可能指向DIP
- 所有的请求报文经由Director Server,但响应报文必须不能经过Director Server
- 不支持端口映射
- RS的系统必须支持隧道
- 通过ipip或者gre模式能够很好的保留客户端ip
模式缺陷
- 使用场景 全称为Tunneling 隧道,lvs-tun模型比较少用,因为他不能实现全局负载均衡,不能根据用户区域的距离来挑选最近的机房。这个最多为了实现异地容灾来实现的。
1.2.3 NAT模式
链路过程
CIP--VIP,客户端发送请求到LVS负载均衡服务器(虚拟IP,master节点)
- 到达LVS负载均衡服务器后,在网络内核中,进行四表五链路由处理
- 进入PREROUTING链,进入路由处理前,进行判断,发现VIP是本机IP,转向INPUT链
- 进入INPUT链,IPVS根据IPVSADM设置的路由规则,将目标IP,从VIP>>RIP,转向POSTROUTING链
- 进入POSTROUTING链,进行路由后处理,根据目标IP(RIP),将请求发送到真实服务器
- 进入RIP后,真实服务器处理完请求后,返回响应报文,网络层,RIP--CIP,并将报文发送到负载均衡服务器NAT模式需要设置DS服务器为网关
- 报文返回DS服务器后,DS服务器将SrcIP设置为VIP,并返回给客户端
LVS动作
- 将DestIP目标地址IP修改为RIP,从网络层做改变
模型特性
- RS应该使用私有地址,RS的网关必须指向DIP
- DIP和RIP必须在同一个网段内
- 请求和响应报文都需要经过Director Server,高负载场景中,Director Server易成为性能瓶颈
- 支持端口映射 NAT可以对端口进行映射到真实服务器
模式缺陷
- 对Director Server压力会比较大,请求和响应都需经过director server
- 使用场景 全称为Network Address Translation,建议小规模使用
1.2.4 FULLNAT模式
FULLNAT工作流程分析:
- 客户端向VIP发送请求
- lvs接收请求,对请求报文做FULLNAT处理,把源IP改为DIP,目标IP改为某个后端RS的RIP,并将请求报文发给该RS。
- RS收到请求后,会进行响应,响应报文的源IP为RIP,目标IP为DIP。
- lvs接收到响应后再次进行FULLNAT处理,将源IP改为VIP,目标IP改为CIP。
从以上的过程可以看出,FULLNAT是通过同时修改报文的源IP(SNAT)和目标IP(DNAT)来实现转发的。
FULLNAT模式有如下特点:
- VIP为公网IP,RIP和DIP为私网IP,且RIP跟DIP一般不在同一网络,因此RIP网关不会指向DIP。
- RS接收到的请求报文源IP是DIP,所以会响应给DIP。lvs要将其发往客户端,需要再次修改源IP和目标IP。
- 请求和响应报文都需要经过lvs。
- 相对于NAT模式,可以更好地实现lvs与RS间跨VLAN进行通信。
- 支持端口映射。
- 值得说明的是,linux内核默认不支持这种模式。
1.2.5 4种模式的差异
1.3. 负载均衡的均衡算法
负载均衡算法是一组规则,负载均衡器遵循这些规则来确定最适合每个不同客户端请求的服务器。负载均衡算法分为两个主要类别。
1.3.1 静态负载均衡
静态负载均衡算法遵循固定规则,与当前服务器状态无关。以下是静态负载均衡的示例。
1.3.2 轮询法
服务器的 IP 地址通知客户端将请求发往何处。IP 地址是一串很难记住的长数字。为了简单起见,域名系统将网站名称映射到服务器。当您在浏览器中输入 aws.amazon.com 时,请求将首先发送到我们的名称服务器,该服务器会将我们的 IP 地址返回给您的浏览器。
在循环法中,权威性名称服务器(而不是专用硬件或软件)执行负载均衡。该名称服务器轮流或以循环方式返回服务器场中不同服务器的 IP 地址。
1.3.3 加权循环法
在加权循环负载均衡中,您可以根据服务器的优先级或容量为每台服务器分配不同权重。权重较高的服务器将从名称服务器接收更多的传入应用程序流量。
1.3.4 IP 哈希法
在 IP 哈希法中,负载均衡器将对客户端 IP 地址执行名为哈希的数学计算。它将客户端 IP 地址转换为数字,然后将该数字映射到各个服务器。
1.3.5 动态负载均衡
动态负载均衡算法将在分配流量之前检查服务器的当前状态。以下是动态负载均衡算法的一些示例。
1.3.6 最少连接法
连接是客户端与服务器之间的开放通信渠道。当客户端向服务器发送第一个请求时,客户端将进行身份验证,并在彼此之间建立活动连接。在最少连接法中,负载均衡器将检查哪些服务器的活动连接最少,并将流量发送到这些服务器。此方法假定所有连接均要求所有服务器具有相同处理能力。
1.3.7 加权最小连接法
加权最小连接算法假定某些服务器可以处理比其他服务器更多的活动连接。因此,您可以为每台服务器分配不同的权重或容量,负载均衡器会将新的客户端请求发送到按容量计算连接最少的服务器。
1.3.8 最短响应时间法
响应时间是服务器处理传入请求和发送响应所花费的总时间。最短响应时间法会将服务器响应时间与活动连接相结合,以确定最佳服务器。负载均衡器使用此算法来确保为所有用户提供更快的服务。
1.3.9 基于资源的方法
在基于资源的方法中,负载均衡器通过分析当前服务器负载来分配流量。称为代理的专用软件在每台服务器上运行,并计算服务器资源的使用情况,如其计算容量和内存。然后,负载均衡器将先检查代理是否有足够的可用资源,然后再将流量分配给该服务器。
1.4. 健康检查
1.4.1 基于心跳检测
负载均衡器周期性地向后端服务器发送心跳请求,如果服务器能够正常响应,则被认为是健康的,否则被认为是不可用的。
1.4.2 基于端口检测
负载均衡器尝试连接后端服务器的特定端口,如果连接成功,则被认为是健康的,否则被认为是不可用的。
1.4.3 基于HTTP请求检测
负载均衡器发送一个包含特定路径和参数的HTTP请求到后端服务器,如果服务器能够正常响应,并返回预期的HTTP状态码,则被认为是健康的,否则被认为是不可用的。
1.4.4 基于TCP检测
负载均衡器尝试与后端服务器建立TCP连接,如果连接成功,则被认为是健康的,否则被认为是不可用的。
1.4.5 基于DNS检测
负载均衡器通过DNS查询来验证后端服务器的可用性,如果查询成功,则被认为是健康的,否则被认为是不可用的。
2. 7层负载均衡
2.1 域名uri转发配置
7层负载均衡器可以通过URI转发来将客户端请求转发给后端服务器。URI转发是基于请求的URI路径来进行负载均衡的一种方法。
当客户端发送请求到负载均衡器时,负载均衡器会解析请求的URI路径,并根据一定的规则将请求转发给相应的后端服务器。这个规则可以是根据URI路径的匹配规则,也可以是通过配置文件中定义的转发规则。
例如,当客户端发送一个请求的URI路径是"/api/users",负载均衡器可以将该请求转发给后端服务器集群中的一个或多个处理"/api/users"路径的服务器。如果负载均衡器发现其中一个后端服务器的负载过高,它可以将请求转发到另一个负载较低的服务器上,以实现负载均衡。
URI转发可以根据不同的URI路径进行配置和管理,可以根据业务需求进行调整和优化。例如,可以为一些常用的URI路径分配更多的处理能力,以确保这些重要的业务功能能够得到及时的响应。
总之,通过URI转发,7层负载均衡器可以根据请求的URI路径将请求转发给相应的后端服务器,以实现负载均衡和优化性能。
2.2 获取客户端ip
通常7层负载均衡通过X-Forwarded-For头字段 设置客户端的ip,
X-Forwarded-For头字段:一般情况下,负载均衡服务器会在HTTP请求头中添加X-Forwarded-For头字段,该字段的值为客户端的真实IP地址。在应用程序中,你可以通过获取该头字段的值来获取到客户端的IP地址。
3. 常见的负载均衡产品
3.1lvs
可以参考 LVS介绍及工作原理图解
3.3 keepalive
可以参考 Keepalived详细介绍简介
3.4 nginx
可以参考 Nginx 介绍
4. 疑问和思考
4.1该如何设计负载均衡产品能够满足各类需求?
通常情况下不能。不同需求下设计的负载均衡产品不一样,需要根据实际情况进行设计和调整。
4.2 udp协议如何做健康检查?
由于udp协议不能建立准确的链接,不能期望rs的端口能够给常规udp拨测请求提供正常的响应,因此通常使用ping拨测来判断后端是否正常
。只要能够响应ping请求,就认为后端是正常的。实际上通过这种模式的健康检查,很难真实的感知后端rs是否异常,但是目前还木有找到更好办法。除非专门跟应用设计专门的协议来判断后端rs的健康状态。
5. 参考文档
- 可以参考 LVS介绍及工作原理图解
- 可以参考 Keepalived详细介绍简介
- 可以参考 Nginx 介绍