情景导入
当电商平台大促时,几十万用户同时涌入抢单,有的服务器忙到崩溃、有的却闲着没事,用户要么页面卡半天刷不出来,要么付完款订单却没生成,甚至某台服务器突然宕机导致一批用户直接无法操作,怎么才能让所有请求被合理分配、服务器不偏科过载?
LB集群(Load Balance Cluster)
LB(负载均衡)集群,用来将用户请求通过调度器使用调度策略(负载均衡算法)调度到不同的节点上,让整个集群内机器的性能处于一个相对平衡的状态;虚拟服务器LVS(Linux Virtual Sever)可作为LB集群的典型代表。
虚拟服务器LVS
虚拟服务器LVS作为 Linux 内核级的四层(传输层)负载均衡解决方案,使用的是netfilter框架。
LVS通过IP_VS内核模块直接干预数据包转发流程,通过修改数据包的关键网络字段(IP、MAC、端口或隧道头),实现将客户端请求分发到后端真实服务器(RS)。
LVS全程不涉及应用层数据解析,仅依赖 TCP/IP 协议栈的传输层及以下信息(IP 地址、端口号),因此性能极高。
LVS数据包修改逻辑与工作模式深度绑定,核心原理可结合三种经典模式(NAT、DR、TUN)的数据包流转过程详解。
LVS在企业IT架构中的位置如图下所示:
LVS 集群组成
前端:负载均衡层
由一台或多台负载调度器构成
中间:服务器群组层
由一组实际运行应用服务的服务器组成
底端:数据共享存储层
提供共享存储空间的存储区域
LVS术语
VIP: 浮动IP ——> 业务IP(提供给用户访问的IP地址)
DIP:LVS上访问真实服务器的接口IP
RIP:业务服务器(真实服务器)的IP地址
CIP: 客户端IP地址
RS: 真实服务器
DS: LVS的负载调度器
LVS的架构
用户态管理程序:ipvsadm————用来管理lvs集群工具
内核态数据包模块:IP_VS————通过netfiler的网络子系统来修改数据包,达到数据转发的目的
LVS的安装
yum install ipvsadm -y
LVS的管理方式
ipvsadm的工具来进行管理,唯一的集群配置文件在/etc/sysconfig/ipvsadm中保存,如果启动ipvsadm的服务将会自动加载该配置文件
ipvsadm --help 查询选项
LVS的工作模式和调度算法
一共有四种工作模式,十二种调度算法
LVS 的三种工作模式
LVS/NAT
LVS/DR
LVS/TUN
LVS 的十二种调度算法
RR、WRR、SH、DH、LC、WLC、SED、NQ、LBLC、LBLCR、FD、OVF
LVS的调度算法的分类:
静态算法: 就是根据规则进行调度(根据算法本身进行调度)
动态算法: 就是根据业务的承载进行调度
静态算法分类:
RR:轮询算法
调度器将收到的请求按顺序轮流分配到集群中的RS。均匀地分配请求,不考虑服务器连接数和负载情况
WRR:加权轮询算法
根据RS的处理能力给予不同的权重,为性能好的服务器分配更多的请求,性能一般的分配较少的请求
SH:源地址哈希算法
根据请求的源IP地址作为哈希键从静态分配的哈希表中找出对应的服务器。同一个IP地址的请求始终发往第一次调度的RS,可实现会话绑定
DH:目的地址哈希算法
根据请求的目标IP地址作为哈希键从静态分配的哈希表中找出对应的服务器。发往同一个目标地址的请求始终转发到第一次调度的RS,可用于实现正向代理缓存场景中的负载均衡
八种 动态算法:
LC:最少连接算法
动态地将网络请求调度到连接数最少的RS上。当集群中的服务器性能相近时,这种算法可以进行较好的均衡负载。适用于长链接应用。其负载计算公式为:overhead = 活动连接数*256+非活动连接数
WLC:加权最少连接算法
相对于LC,当集群中服务器性能有差异时,建议使用本算法,可以使性能较好的服务器承接较大比例的活动连接。此算法是LVS的默认调度算法,负载公式为:overhead = (活动连接数*256+非活动连接数)/权重值
SED:最短期望延迟算法
当使用WLC时,如果RS的连接数和权重比例正好一样时,下个请求将可能分配给任意一个RS,而不是性能最好的RS,SED可避免这种情况,保证了高权重优先
NQ:最少队列算法
使用该算法时,第一轮请求会均匀的分配给所有RS,后续再使用SED算法,这样可以避免某些服务器可能用于得不到处理请求的机会
LBLC:基于局部的最少连接算法
根据请求的目标IP找出该目标IP最近使用的服务器,若该服务器可用且没超载,就将请求发给它;若服务器不存在或者超载,且有服务器处于一半的工作负载,则用最少连接原则将请求发给一个可用服务器。是针对目标IP地址的负载均衡算法,可以看作动态的DH算法。可根据负载情况实现正向代理、web缓存等
LBLCR:加权最少连接算法
该算法维护从一个目标IP地址到一组服务器的映射(lblc维护的是一个目标IP地址到一台服务器的映射)。根据请求的目标IP找出该目标IP对应的服务器组,按最少连接原则从组内选出一台没有超载的服务器,将请求发给它;若该服务器超载,则最少连接原则从该集群中选出一台服务器加入到服务器组中,将请求发给该服务器。如果服务器组在一段时间没有修改,将最忙的服务器从组内剔除,以降低复制程度。这个算法也是针对目标IP地址的负载均衡算法,解决lblc负载不均衡的问题,从负载重的RS复制到负载轻的RS。可根据负载情况实现正向代理、web缓存等
FO:Weighted Fail Over算法
该算法会遍历lvs关联的RS链表,找到未过载(未设置IP_VS_DEST_F_OVERLOAD标识)且权重最高的RS进行调度
OVF:Overflow-connection
基于RS的活动连接数和权重值来实现。它会将新连接调度到权重值最高的RS,直到其活动连接数超过它的权重值,之后调度到下一个权重值最高的RS。该算法会遍历lvs关联的RS链表,找到权重值最高的可用RS。可用RS需要满足以下条件:LBLCR:加权最少连接算法
未过载(未设置IP_VS_DEST_F_OVERLOAD标识)
RS当前活动连接数小于其权重值
权重值不为0
mh 动态调度算法
LVS/NAT模式
LVS/NAT模式的特点:
1. 集群和LVS的节点要在同一个网络之中,并且LVS的DIP要充当RS的网关地址
2.LVS要在客户端和真实服务器端进行数据转发,也就是DS的服务器需要支持ip转发
3.RS的服务器可以是任意的操作系统(就是单纯的业务节点,无需做任何集群相关的配置)
4. LVS 支持端口映射给后端服务器
5.因为所有的流量都需要通过LVS进行转发,就会导致LVS成为 集群瓶颈,在NAT模式下单台LVS一般承载10 -15 台真实服务器,原因是大量用户请求的数据包很小,但多台服务器返回的资源很大而导致LVS有巨大压力
LVS/NAT 模式的完整请求—响应流程:
- 请求发起阶段:客户端通过自身 IP(CIP),向 LVS 集群对外暴露的虚拟服务 IP(VIP)发起业务请求,此时数据包的源地址为 CIP、目的地址为 VIP。
- LVS 调度与地址转换:请求到达 LVS 调度器后,内核的ip_vs模块会依据预设的调度算法(如轮询、加权轮询),从后端真实服务器池(Real Server)中选定一台目标服务器(对应 RIP);随后 LVS 会对数据包执行目的地址转换(DNAT):保持源地址(CIP)不变,将目的地址从 VIP 修改为选中的 RIP,再将数据包转发至该 RIP 服务器。
- 后端服务器处理请求:RIP 服务器接收到数据包后,识别到目的地址是自身 IP,便正常处理业务请求(如提供 Web 服务、执行接口逻辑)。
- 响应回传阶段:RIP 处理完请求后,生成的响应数据包源地址为自身 RIP、目的地址为客户端 CIP;但由于 RIP 通常处于内网网段(与 LVS 的内网 IP(DIP)同属私有网络),无法直接与公网的 CIP 通信(网络不可达),因此 RIP 会将响应包发送至自身配置的网关 —— 而该网关正是 LVS 的 DIP。
- LVS 二次地址转换与回包:LVS 收到 RIP 的响应包后,会执行源地址转换(SNAT):将数据包的源地址从 RIP 修改为 LVS 的 VIP,目的地址保持 CIP 不变;此时 LVS 需开启内核的IP_forward(IP 转发)功能(相当于一台具备 NAT 能力的路由器),最终将修改后的响应包转发至公网,送达客户端。
LVS/NAT实验架构:
实验需求:client访问http://192.168.31.99依次调度到192.168.1.12和192.168.1.13上
基础环境准备:
在两台作为RS的主机上安装并配置Nginx用于测试
配置RS的IP地址和网关配置,RS的网关一定要指向DIP
在LVS上配置IP地址
修改内核参数开启内核转发功能
配置LVS负载均衡集群:
yum安装LVS
在LVS上添加虚拟服务器和真实服务器
ipvsadm -A -t 192.168.31.99:80 -s rr 创建集群服务并指定调度算法为rr,默认是wlc加权轮询
ipvsadm -a -t 192.168.31.99:80 -r 192. 168.1.12 -m 向集群内添加真实服务器并指定工作模式为nat
ipvsadm -a -t 192.168.31.99:80 -r 192. 168.1.13 -m
进行访问测试(可以看到调度成功)
补充:NAT模式下利用LVS实现端口映射
LVS/NAT 的端口映射,是靠内核ip_vs模块的 “双向地址 + 端口转换”+“连接跟踪表” 实现的:客户端请求(CIP:CPort→VIP:VPort)到 LVS 后,ip_vs选后端 RIP,把 “目的 IP: 端口” 改成 “RIP:RPort”(DNAT),同时记录 “CIP:CPort↔VIP:VPort↔RIP:RPort” 的对应关系;
后端响应(RIP:RPort→CIP:CPort)到 LVS 后,ip_vs查连接表,把 “源 IP: 端口” 改回 “VIP:VPort”(SNAT),再发给客户端。
这里用实验进行验证,将DS(192.168.31.99)的8888端口映射至RS(192.168.1.13)的22端口,通过ssh访问进行测试
ssh连接192.168.31.99:8888登录至192.168.1.13,端口映射成功
LVS/DR模式
LVS/DR模式的特点:
1. DIP与RIP之间必须在同一个局域网络中
2. 每一台RS节点都必须有自己真实的网关,且网关不能指向DIP
3.RIP可以不是私网地址,可以真正的访问网络
4. DR模式下无法实现端口映射
5.RS节点所在的操作系统,必须支持屏蔽ARP(通常是LINUX,通过Linux的内核参数来屏蔽ARP)
6.负载的能力更强,DR模式下LVS只有下行流量,上行流量由真实的服务器直接回应客户端,因此业务的承载量通常是nat的数十倍
这是 LVS/DR 模式的请求—响应流程:
1.ARP 屏蔽与 VIP 独占准备:LVS 调度器(DS)提前通过 ARP 协议获取集群内所有后端真实服务器(RS)的 RIP 与 MAC 地址;同时在 RS 上配置 ARP 屏蔽规则(如禁用 VIP 的 ARP 广播、限制 ARP 响应),避免集群内多台设备(LVS+RS)同时响应 VIP 的 ARP 请求 —— 确保仅 LVS 的 VIP 对外响应 ARP,使客户端请求的数据包能准确发往 LVS。
2.请求转发阶段:客户端向 VIP 发起请求,数据包的目的 MAC 为 LVS 的 MAC(由 ARP 响应确定);请求到达 LVS 后,LVS 不修改数据包的 IP(源为 CIP、目的为 VIP),仅修改二层 MAC 地址:将数据包的源 MAC 改为自身 MAC,目的 MAC 改为选定 RS 的 MAC,随后通过二层网络直接转发给该 RS(因 LVS 与 RS 处于同一物理网段,无需路由)。
3.响应回包阶段:RS 收到数据包后,因自身 lo 接口已绑定 VIP(仅用于接收目的 IP 为 VIP 的包,不对外广播),可正常处理请求;处理完成后,RS 生成响应包:源 IP 为 VIP、源 MAC 为自身 MAC,目的 IP 为 CIP、目的 MAC 为客户端的 MAC(RS 通过 ARP 获取),直接将响应包发往客户端 —— 无需经过 LVS,大幅减轻了 LVS 的回包负载压力。
Nginx 这类 7 层负载均衡属于 “代理模式”,所有请求与响应都需经过 Nginx 转发,无法实现 “回包绕开调度器”,因此 LVS/DR 的负载压力远低于前者。
LINUX系统模拟路由器的配置:
1. 给路由器增加两张网卡 分别使用net8和net1
2. 在路由器上开启ip_forward转发内核参数
3. 在路由器的防火墙上开启地址伪装(NAT)
LVS集群的配置:
在eth0上添加IP地址作为VIP(也可以和真实服务器一样添加在环回接口上)
修改内核参数开启IP转发
配置LVS集群
RS的配置:
将VIP地址配置在dummy类型的换回口上(由于添加的是相同的IP地址,所以不能直接添加在物理网卡上,否则会引起IP地址冲突。 因此只能配置在由系统模拟出来的lo网卡,dummy 接口是 Linux 系统为弥补 loopback 接口数量)限制而推出的模拟环回类接口)
nmcli connection add type dummy ifname dummy1 con-name dummy1 ipv4.method manual ipv4.addresses 192.168.31.100/32 autoconnect yes
配置RS(Nginx1、Nginx2)禁止响应ARP
net.ipv4.conf.dummy2.arp_ignore=1
net.ipv4.conf.all.arp_ignore=1
默认值0
0 表示任意的接口收到ARP就会响应
1 仅目标IP在本机上才响应ARP
LVS DR 模式的关键是所有真实服务器和调度器共享同一个 VIP,但只有调度器能对外响应 VIP 的 ARP 请求(告诉网络 “VIP 的 MAC 地址是我”)。如果真实服务器也响应 ARP 请求,会导致网络中多个设备声称自己拥有 VIP 的 MAC 地址,引发 ARP 冲突、请求分发混乱,最终负载均衡失效。
两段配置为什么要一起配置?
1. 只配置 net.ipv4.conf.all.arp_ignore=1(仅全局规则)
表面效果:看似可行,因为all是 Linux 内核中对所有网络接口的 “全局兜底规则”,理论上会覆盖 dummy2、物理网卡(如 eth0)、lo 等所有接口的arp_ignore值,让所有接口都遵循 “仅目标 IP 在接收接口上才响应 ARP” 的规则。
潜在致命风险:Linux 的接口参数优先级是 “局部接口配置> all 全局配置”。如果后续有人误操作(比如为 dummy2、eth0 单独配置arp_ignore=0),或者系统升级 / 其他脚本修改了某接口的局部参数,全局的all.arp_ignore=1会被覆盖,导致真实服务器重新响应 VIP 的 ARP 请求,引发 MAC 地址冲突,LVS DR 负载均衡直接失效。
2. 只配置 net.ipv4.conf.dummy2.arp_ignore=1(仅 VIP 所在接口)
直接失效:这是完全错误的配置方式。ARP 请求是发送到真实服务器的物理网卡(如 eth0)的(而非 dummy2 接口),而你仅配置了 dummy2 接口的arp_ignore=1,物理网卡的arp_ignore仍为默认值 0。此时物理网卡收到针对 VIP 的 ARP 请求时,会因为 “本机 dummy2 接口配置了 VIP”(默认值 0 的逻辑)而响应 ARP,直接导致网络中多个设备(LVS 调度器 + 真实服务器)同时响应 VIP 的 MAC 查询,引发 ARP 冲突,LVS DR 模式彻底无法工作。
3. 两段配置同时配置的效果
net.ipv4.conf.all.arp_ignore=1:全局规则,确保所有接口(物理网卡、dummy2、lo 等)默认遵循 “不响应非本接口 IP 的 ARP 请求”,从根本上杜绝物理网卡响应 VIP 的 ARP 请求;
net.ipv4.conf.dummy2.arp_ignore=1:局部精准规则,针对 VIP 所在的 dummy2 接口锁定规则,防止后续局部配置覆盖全局规则。
配置RS(Nginx1、Nginx2) ARP的通告级别
net.ipv4.conf.all.arp_announce=2
net.ipv4.conf.dummy2.arp_announce=2
默认值 0
0 表示向每个接口通告ARP
2 表示避免向非本网络进行通告
这样配置是为了使RS在回包时VIP所在接口不进行ARP通告,只让RIP进行通告,防止引发ARP冲突
测试结果
查看调度的数据包
保存配置方式(将配置到处至指定的文件后,启动ipvsadm服务时可读配置)
LVS/TUN模式—解决DIP和RIP不在同一个局域网内的问题
隧道模式:就是在原有的IP报文基础上封装一层IP报文
LVS的隧道模式
实现方式,在DR模式的基础上,封装一层IP报文,该IP报文源IP是LVS的DIP,目的IP是LVS根据负载均衡的调度算法选择出来的RIP,当请求达到RIP以后,此时RS根据IP隧道解封装,然后由RS直接处理客户端的响应
特点:
1. DIP和RIP不再需要在同一个局域网内,但是DIP和RIP以及VIP都要是公网地址
2. RS的真实服务器必须要支持IP隧道协议(ipip隧道、gre隧道、gue隧道,默认使用的是IPIP协议,一般的LINUX都可以支持)
3. ip隧道模式也不支持端口映射
4. 支持RS的数量非常多,但是需要更多的公网IP地址
补充:FULL-NAT: 全NAT模式
同时修改请求的源IP和目的IP进行地址转发,因此可以在多个vlan之间进行NAT转发
1. VIP必须是公网地址,RIP和DIP都只能私网地址,并且RIP和DIP通常不应该在一个局域网内,且有多个vlan的环境,所以RIP的网关也不会指向DIP
2. RS收到请求的源地址是来自DIP,因此RIP虽然不指向DIP,但是必须将数据包发给DIP,也就是要响应DIP,最终的所有流量都要通过LVS发送给客户端