LVS负载均衡实战:DR模式部署与keepalived高可用配置
2026/9/18 6:22:22 网站建设 项目流程

刚组里来了个新同事,简历上写着“熟悉负载均衡”,结果我让他解释一下生产环境里LVS的keepalived配置,他盯着屏幕看了半天说不出个所以然。这个现象我见得太多了——很多人嘴上说的“负载均衡”其实是Nginx七层代理,而对真正扛住超大流量入口的四层负载均衡LVS,基本停留在“听过名字”的阶段。

这篇文章不是教科书式的原理梳理,而是冲着标题里那句“看完就能去上班”去的。我会把LVS的核心原理、三种工作模式的取舍、生产部署的完整命令、keepalived高可用配置,以及一线最容易踩的坑全部过一遍。适合两类人看:一类是准备面试的运维或后端开发,另一类是刚接手LVS环境、急需上手干活的同学。看完你能做到三件事:说清楚LVS和Nginx的区别、独立部署一套DR模式的LVS+keepalived集群、遇到诡异问题知道从哪里下手排查。

1. 先搞明白四层负载均衡在架构里是什么位置

1.1 一次完整请求,LVS到底卡在哪个环节

想象一下你打开一个电商网站首页。浏览器先做DNS解析,拿到域名对应的入口IP,然后发起HTTP请求。这个入口IP背后不是一台Web服务器,而是一整片服务器集群。流量进入机房的第一站,往往就是一组四层负载均衡器——也就是LVS。

LVS在这条链路里的角色非常纯粹:它只根据数据包的目标IP和端口,决定把连接转给后面哪台真实服务器(RealServer,简称RS)。它不拆开应用层数据,不看HTTP路径,不关心你是GET还是POST,甚至不知道协议内容是JSON还是HTML。

正因为LVS工作在较底层,它才能做到极高的转发性能。整个请求链路通常是这样的:

客户端 -> DNS解析到VIP -> LVS(四层入口) -> Nginx(七层反向代理/静态资源) -> 应用服务 -> 数据库

LVS在最前面做流量入口,Nginx在它后面做精细化路由,二者是上下游关系,不是替代关系。很多面试者被问到“LVS和Nginx有什么区别”时直接懵,本质就是没想清楚这条链路。

1.2 为什么有Nginx还要用LVS:性能账和架构账

先给结论:Nginx是七层负载,LVS是四层负载,性能不在一个量级。

Nginx处理一个请求时,需要和客户端建立TCP连接、解析HTTP头部、按规则转发、维护连接状态,这些都是用户态的CPU密集操作。单机Nginx能扛的并发连接数和每秒新建连接数都有明确的上限,几十万并发时CPU早就吃满了。

LVS不一样。它把负载均衡逻辑做进了Linux内核,通过IPVS模块直接修改数据包的目标地址或MAC地址完成转发,整个过程不需要把数据包从内核态拷贝到用户态,也就没有上下文切换的开销。单台LVS转发能力可以达到几十万甚至上百万并发连接,这根本不是Nginx能比的数量级。

所以生产架构里最常见的组合是:LVS在入口扛流量冲击,Nginx在业务层做灵活的七层路由、限流、缓存、跨域处理。面试时被问到这个问题,能把这个层次关系画出来,再补一句“LVS转发的是连接/数据包,Nginx转发的是HTTP请求”,基本就过关了。

1.3 理解“四层”到底拆到哪一层

说LVS是“四层负载均衡”,这里的四层指的就是TCP/IP模型里的传输层。复习一下TCP/IP四层模型,自上而下分别是应用层、传输层、网络层、网络接口层

  • 应用层:处理具体业务数据,比如HTTP、HTTPS、SSH,对应我们平时写的业务代码。
  • 传输层:提供端到端的通信能力,核心是TCP和UDP协议,引入端口概念,保证数据可靠到达对方进程。
  • 网络层:负责寻址和路由选择,核心是IP协议,数据包要经过哪些路由器到达目标网段由这一层决定。
  • 网络接口层:最底层,负责物理介质上的实际传输,比如以太网帧的收发,MAC地址就是在这一层发挥作用。

LVS工作在传输层,只处理TCP/UDP的报文头,最多看到端口和IP地址,完全不会解析HTTP报文内容。理解了这个定位,你就明白为什么LVS可以做MySQL、Redis、DNS这类非HTTP服务的负载均衡——只要走TCP/UDP协议,LVS就能管。这也是它比七层负载均衡通用得多的原因。

2. 三种工作模式选型:NAT、DR、TUN各自的脾气

LVS有三种工作模式,面试必问,生产选型更是绕不开。很多人背了概念却不知道各自适用的场景,导致部署时选了错误的模式,排错排到怀疑人生。

2.1 用一个包的三段旅程看懂三种模式

我直接对比三种模式下,一个数据包从客户端到服务器、再从服务器回客户端的完整旅程。

VS/NAT模式(地址转换)

客户端把包发给LVS的VIP,LVS收到后把包的目标IP改成某台RS的内网IP,同时记录连接状态;RS处理完,把响应包先回给LVS,LVS再把包的源IP改回VIP,然后发给客户端。

特点:请求和响应都经过LVS,LVS是必经之路。改IP的行为和家用路由器做端口映射非常像。

VS/DR模式(直接路由)

客户端把包发给LVS的VIP,LVS收到后不改IP,只把包的目标MAC地址改成某台RS的MAC,然后通过二层网络直接发给RS。RS收到后发现自己本来就是VIP的持有者(VIP配在lo接口上),正常处理请求,响应包直接从自己的网卡发回客户端,源IP仍然是VIP。

特点:请求经过LVS,响应不经过LVS,转发路径是最短路径,性能最高。

VS/TUN模式(IP隧道)

LVS把客户的请求包再用一个新的IP包头封装起来,外层目标IP是RS的IP,发送到RS后,RS解封装还原出原始包,处理后直接从自身IP回给客户端。

特点:可以跨网段、跨机房部署,RS不需要和LVS在同一二层网络,但每台RS都要支持IP隧道协议,封装和解封装有一定开销。

2.2 为什么生产环境默认DR:性能压倒一切

DR模式成为生产环境绝对主流,核心原因只有一个:响应流量不经过LVS,避免了LVS成为吞吐瓶颈。

在NAT模式里,LVS要承担全部进站和出站流量。下载场景、视频流场景这类“响应数据远大于请求数据”的业务,出站流量会把LVS的带宽和CPU打满。DR模式下RS直接把响应发给客户端,LVS只处理后端服务器回程带宽的零头,压力小一大截。

但DR模式有一个严苛前提:LVS和各RS必须在同一个二层网络里。因为LVS要修改目标MAC地址,而MAC地址只能在本网段内通信。同时,每台RS都必须把VIP绑在lo环回接口上,并且严格抑制对VIP的ARP响应。如果不这么做,交换机的ARP表里VIP对应的MAC可能变成某台RS的MAC,流量就会被交换机直接转发给RS,根本轮不到LVS做调度,整台负载均衡器就形同虚设。

2.3 NAT和TUN哪些场景才用得上

NAT模式虽然性能受限,但它的优势是不要求RS和LVS在同一网段,也不要求RS的OS是Linux。如果你要负载均衡的是一批Windows服务器,或者RS在完全不同的网段,NAT是唯一不需要隧道就能工作的选择。NAT模式需要开启内核的ip_forward功能,还要保证RS的默认网关指向LVS,否则响应包会绕过LVS直接发给客户端,导致连接失败——这就是非对称路由问题。

TUN模式适合跨机房、跨地域部署的场景,比如两个数据中心各有一批RS,通过TUN模式可以统一调度。但国内网络环境里物理链路延迟、专线质量等问题会让隧道封装的性能优势打折扣,实际生产环境用得远比DR少。

下面这张表可以帮你快速决策:

模式改的是什么请求路径响应路径瓶颈点适用场景
NAT目标IP/源IP客户端→LVS→RSRS→LVS→客户端LVS带宽和CPURS异网段、RS是Windows
DR目标MAC客户端→LVS→RSRS→客户端二层网络依赖同机房、性能优先
TUN新增IP封装客户端→LVS→隧道→RSRS→客户端隧道开销跨机房、跨地域

3. 跟着我做一遍DR模式部署:从两台CentOS到上线

这个章节是全文的实操核心,我会把每一步命令、每个参数的含义、配置完之后怎么验证,全部展开讲。你手边有虚拟机就能完整复现。

3.1 网络拓扑和IP规划

我用三台CentOS 7/8(或Rocky Linux)来做演示:

角色接口IP地址说明
LVS负载均衡器(Director)eth0192.168.1.10另配VIP:192.168.1.100
真实服务器RS1eth0192.168.1.11lo:0绑定VIP
真实服务器RS2eth0192.168.1.12lo:0绑定VIP
客户端eth0192.168.1.50用于访问测试

所有机器在同一个交换机下,网关是192.168.1.1。后端RS上都安装了nginx并监听80端口,提供不同的测试页面用于区分转发效果。

3.2 Director配置四步走

第一步:确认内核加载了IPVS模块

LVS的内核模块叫ip_vs,在部分Linux发行版上默认没有加载。执行:

modprobe ip_vs

然后确认模块已加载:

lsmod | grep ip_vs

如果没有任何输出,说明modprobe没生效,检查一下内核是否包含IPVS支持,或者重启后再试。为了让模块开机自动加载,可以创建一个模块配置文件:

echo "ip_vs" > /etc/modules-load.d/ip_vs.conf

第二步:安装管理工具ipvsadm

IPVS模块是内核里的“发动机”,但要指挥它还得靠用户态的管理工具:

yum install -y ipvsadm

第三步:配置VIP和真实服务器

在Director上把VIP配到eth0上。这里强调一下子网掩码用/32,防止VIP被ARP广播出去引来不必要的干扰:

ip addr add 192.168.1.100/32 dev eth0

然后使用ipvsadm添加负载均衡规则:

# 添加虚拟服务,VIP:80,调度算法加权轮询 ipvsadm -A -t 192.168.1.100:80 -s wrr # 添加真实服务器,-g表示DR模式,-w是权重 ipvsadm -a -t 192.168.1.100:80 -r 192.168.1.11:80 -g -w 1 ipvsadm -a -t 192.168.1.100:80 -r 192.168.1.12:80 -g -w 2

几个参数别搞混:-A是新增虚拟服务,-a是往虚拟服务里加RS;-t后面跟VIP的TCP端口;-r是RS的IP和端口;-g对应DR模式,-m对应NAT模式,-i对应TUN模式。Work中80%的配置错误都出在忘了带模式参数,默认不带的话IPVS会把RS当作本地路由处理,流量进来直接转发去但响应回不来。

第四步:查看当前负载均衡规则

ipvsadm -Ln

输出大致长这样:

IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.1.100:80 wrr -> 192.168.1.11:80 Route 1 0 0 -> 192.168.1.12:80 Route 2 0 0

看到Route就说明DR模式已经生效了,这是DR模式在ipvsadm里的显示特征。

3.3 真实服务器:VIP放环回口和ARP抑制三板斧

这一步是DR模式最容易出错的地方。两台RS都要执行,核心逻辑是:“我是VIP的持有者,但我绝不对VIP的ARP询问做任何应答”。

第一板斧:把VIP绑到环回接口

ip addr add 192.168.1.100/32 dev lo

为什么绑在lo而不是eth0?因为如果绑在eth0,RS收到对VIP的ARP请求时会向外部宣告“VIP在我这里”,交换机会把VIP的MAC地址改成这台RS的MAC,后续流量全被它截获,LVS就再也没有机会调度了。

第二板斧:修改ARP内核参数

修改/etc/sysctl.conf,添加以下内容:

net.ipv4.conf.all.arp_ignore = 1 net.ipv4.conf.all.arp_announce = 2 net.ipv4.conf.lo.arp_ignore = 1 net.ipv4.conf.lo.arp_announce = 2

然后让配置生效:

sysctl -p

解释这两个参数:

  • arp_ignore=1:只回答目标IP是本接口IP的ARP请求。比如外界问“谁是192.168.1.100”,RS的lo接口绑了这个IP,但RS的eth0接口没有,所以RS不会抢答。这能防止RS和LVS抢VIP。
  • arp_announce=2:发送ARP请求时,尽量用能到达对端的最佳本地地址,避免使用VIP这个“非本地物理网卡”的地址去通告自己。

可以拿一个生活场景来类比:VIP就像一个公司的统一总机号码,LVS是前台接线员,所有外部来电都打到总机,由前台转给对应的工位。RS就是后面的员工,员工知道自己代表公司对外服务,但绝不能把自己的私人手机号对外公布,否则客户就直接绕过前台打员工电话了。

第三板斧:关闭反向路径过滤

某些内核版本在开启rp_filter时,会因为VIP在lo接口上而产生反向路径校验失败,导致RS收不到包或发不出包。建议在配置里显式关闭:

net.ipv4.conf.all.rp_filter = 0 net.ipv4.conf.eth0.rp_filter = 0

配置完成后重启网络服务或整机重启验证参数是否生效。

3.4 跑通链路和查看统计

在Director上确认规则都在,RS确认nginx都启动后,从客户端机器发起请求:

curl http://192.168.1.100

初次访问可能打到一个页面。多刷新几次,然后在Director上执行:

ipvsadm -Ln --stats

如果看到两个RS的ActiveConnInActConn在累计增长,说明转发已经跑通了。为了更直观地验证DR模式“响应不走Director”的特性,可以在RS1上抓包:

tcpdump -i eth0 host 192.168.1.100 and port 80

你会发现到达RS的请求包,源IP是客户端IP而不是LVS的IP——因为DR模式只改了MAC地址,完全没有碰IP头。

如果发现流量只分给某一台RS,先看RS权重、再看调度算法的hash缓存,最后看RS是不是因为健康检查失败被摘除了。

4. keepalived接管:单节点不是生产,高可用才是

4.1 为什么必须上keepalived:单点故障的现实教训

手动配好IPVS规则后,整个服务就能跑了,但这时候Director是单点。网线被误拔、服务器重启、内核panic,任何一个意外都意味着整个入口瘫痪。之前就有一次,机房夜间检修,值班同事误碰了Director的电源,结果整站五分钟内不可用——因为所有人的手动配置都在那台机器上,备用的空机器根本接不上。

keepalived的出现就是为了解决两个问题:

  1. 通过VRRP协议在多个Director之间做VIP漂移,主节点挂了,备用节点几十秒内接管VIP,继续使用同一套IPVS规则转发流量。
  2. 提供后端真实服务器的健康检查,RS端口异常时自动从IPVS列表中摘除,恢复后自动加回。

4.2 keepalived.conf逐段注释

安装keepalived:

yum install -y keepalived

主节点配置文件/etc/keepalived/keepalived.conf。我会把每个关键段落的含义写清楚:

global_defs { router_id LVS_MASTER # 可选:开启脚本执行告警,不配置也不影响主流程 } vrrp_instance VI_1 { state MASTER # 主节点身份,备机这里是BACKUP interface eth0 # 承载VRRP报文和VIP的网卡 virtual_router_id 51 # 相同VRRP组内必须一致,用于区分不同集群 priority 100 # 优先级,主节点要高于备节点 advert_int 1 # VRRP通告间隔,单位秒 authentication { auth_type PASS auth_pass 1234 # 主备必须一致,生产建议用复杂一点 } virtual_ipaddress { 192.168.1.100/32 dev eth0 } } virtual_server 192.168.1.100 80 { delay_loop 6 # 健康检查周期,单位秒 lb_algo wrr # 调度算法,要和ipvsadm含义一致 lb_kind DR # 转发模式,保持DR persistence_timeout 0 # 持久连接超时,单位秒;0表示关闭 protocol TCP # 健康检查用TCP协议 real_server 192.168.1.11 80 { weight 1 TCP_CHECK { connect_timeout 3 nb_get_retry 3 delay_before_retry 1 } } real_server 192.168.1.12 80 { weight 2 TCP_CHECK { connect_timeout 3 nb_get_retry 3 delay_before_retry 1 } } }

备节点配置除了state BACKUPpriority 90,其他内容基本一致。注意virtual_router_idauth_pass两台机器必须一模一样,否则VRRP组建立不起来,会出现双主脑裂。

这里对几个参数做些补充说明:

  • persistence_timeout:如果配置成600秒,那么同一个源IP的连接会在600秒内始终调度到同一台RS,相当于LVS层面的会话保持。默认0表示关闭,完全由调度算法决定。
  • TCP_CHECK是端口探测,只要TCP端口能建立连接就算健康。这个方案对“端口通但服务假死”的情况检测不出来,生产建议用HTTP_GET探测一个专门写的health接口。

启动服务:

systemctl enable --now keepalived

启动后确认VIP已经在网卡上:

ip addr show eth0 | grep 192.168.1.100

4.3 主备漂移和后端摘除演练

配置完不是就万事大吉了,建议你立刻做一次破坏性演练。

演练一:主节点宕机

在Master上执行systemctl stop keepalived,然后回到Backup上观察。过几秒后执行:

ip addr show eth0 | grep 192.168.1.100

正常情况下Backup会在这个时间内把VIP绑到自己的eth0上。同时,由于Backup也配置了一套virtual_server规则,它会自动加载IPVS转发规则。整个切换过程用户无感知,只有VIP的MAC地址发生了漂移。

演练二:RS故障自动摘除

把RS1的nginx停掉:

systemctl stop nginx

等一个健康检查周期(delay_loop 6秒加上探测超时),在Director上执行:

ipvsadm -Ln

RS1应该已经从转发列表里消失了。此时即使调度算法轮询到RS1,IPVS也不会再把连接发过去。把nginx重新启动,RS1会在大约一个检查周期后被自动加回。

在中国移动互联网的机房环境里,keepalived本身就是老牌稳定的方案,很多运维团队担心VRRP组播在云主机上不通。如果是云上环境,建议用公有云自带的SLB产品,自建LVS在VPC网络里要开组播非常麻烦;但在自有机房、物理机或KVM虚拟机场景下,keepalived+LVS依然是经典且可靠的选择。

5. 调度算法怎么选:别再只用rr,面试和线上都不够用

5.1 静态算法和动态算法对照

IPVS提供十多种调度算法,核心分成静态和动态两类。静态算法不看后端当前负载,纯粹按预设计算规则分配;动态算法会实时统计每个后端的连接数、延迟等指标再决定分给谁。

算法类型算法名全称/说明适用场景
静态rr轮询,平均分配后端配置相同、无状态服务
静态wrr加权轮询后端配置不同、按权重分配
静态sh源地址哈希需要基于源IP的会话保持
静态dh目标地址哈希按目标IP固定转发
动态lc最少连接,分配给连接数最少的RS长连接场景
动态wlc加权最少连接,连接数除以权重后取最小生产最常用、默认推荐
动态sed最短期望延迟,估算响应时间对延迟敏感的服务
动态nq永不排队,连接数最少的优先分配配合sed使用

如果面试被问到“LVS默认的调度算法是什么”,答案是wlc(加权最少连接)。它的调度公式是计算(active_conn * 256 + inactive_conn) / weight,取结果最小的RS接受新连接。这个公式好在哪里?它同时考虑了当前活动连接数、非活动连接数和机器权重,是“等开销负载均衡”思路的典型实现——让每台后端承担的代价尽量均衡。

5.2 会话保持:LVS只管连接,不背Session的锅

很多初用LVS的人遇到一个经典问题:用户登录后,刷新一下页面就掉线,或者验证码永远不对。原因很简单,用户第一次请求被分给了RS1,登录状态存在RS1的内存里,第二次请求被分给了RS2,RS2不认这个用户的登录态。

LVS本身不维护业务Session,它只负责传输层的连接调度。要解决会话一致性问题有三个思路:

  1. 最彻底的办法:把Session放到外部存储。比如Redis或数据库,让RS变成无状态服务。这样即使请求被分配到任意一台RS,都能从统一存储里取到会话数据。这是目前主流的做法,也方便扩容缩容。
  2. 用LVS的持久连接功能。在keepalived配置里设置persistence_timeout 600,或者在ipvsadm命令里加-p 600,让同一个源IP在600秒内固定到同一台RS。命令行对应的是ipvsadm -A -t 192.168.1.100:80 -s rr -p 600
  3. 使用sh调度算法。源地址哈希算法保证同一个源IP永远被hash到同一台RS,但这种方案有短板:如果某个出口IP后面有大量用户(比如公司统一出口),所有用户都会被固定到一台RS上,流量严重倾斜。

实践里我通常建议方案1为主、方案2兜底,不要单独依赖LVS的持久连接。因为持久连接本质是把并发摊薄到单机,后端容量规划会非常难受。

5.3 生产环境选型建议:什么后端配什么算法

根据后端服务的特性直接套用选型建议:

  • 后端机器规格一致、接口完全无状态:优先wrrrr,简单可控,压测时也容易观察分配是否均匀。
  • 后端机器规格不齐,有性能差异:用wlcwrr并设置权重,让性能好的机器承担更多流量。
  • 长连接服务(WebSocket、数据库代理):用lcsh,避免连接频繁迁移。lc动态效果更好,sh更稳定但可能倾斜。
  • 有Session需求且短期内不想做改造:临时用sh或持久连接,但一定要规划后续迁移到外部Session。
  • 纯内部RPC调用、对延迟敏感:用sednq,这两个算法对短请求的响应体验更友好。

6. 一线踩坑记录:DR模式最容易翻车的几个地方

6.1 VIP通了,但所有流量都打到某一台RS上

这个现象非常典型:LVS配置完全正确,curl VIP也能通,但通过ipvsadm -Ln --stats一看,所有连接都落在同一台RS上,另一台的计数纹丝不动。

第一反应是权重或调度算法的问题,但排查下来往往更隐蔽——ARP层面就已经把流量引偏了。在客户端或网关机器上执行:

arp -n | grep 192.168.1.100

如果看到的MAC地址不是Director网卡的MAC,而是某台RS的MAC,那就说明RS抢答了VIP的ARP请求。几乎可以断定是这台RS的arp_ignore参数没配置或者没生效。

修复方法:回到第3.3节,重新检查那台RS的sysctl配置。特别注意,arp_ignore要同时配置在all和虚拟接口所在的具体接口(lo)上,并且执行sysctl -p后要确认配置存在:

cat /proc/sys/net/ipv4/conf/all/arp_ignore cat /proc/sys/net/ipv4/conf/lo/arp_ignore

两个都应返回1。注意:有些发行版的all接口和具体接口参数是“取最大值”的关系,所以必须都配到位。

6.2 Director一切正常,RS就是收不到包

如果Director上能看到连接计数在涨,但RS的nginx访问日志一条都没有,问题大概率出在链路中间。按顺序排查:

  1. RS防火墙。很多机器默认开启了firewalld,INPUT链默认策略是DROP,来路不明的TCP包直接被丢弃。可以在测试阶段直接systemctl stop firewalld,生产环境要放行80端口的服务访问。
  2. 反向路径过滤。前面反复提到的rp_filter如果开着,RS验包发现源IP的路由出口和入口不一致,直接丢包。生产上建议至少把eth0和all设为0。
  3. 内核参数没生效。改完sysctl.conf没有重启网卡或没有执行sysctl -p,导致RS仍然用旧的配置在跑。
  4. 端口监听地址。如果nginx配置只监听了127.0.0.1:80,那RS网卡收到请求后内核直接拒绝连接。检查ss -lnt确认监听在0.0.0.0:80

排查RS收包最好的工具是tcpdump:

tcpdump -i eth0 host 192.168.1.100 and port 80

如果这个命令在客户端访问VIP时没有任何输出,说明包根本没到RS;有输出但nginx没反应,说明包被上层应用或防火墙丢了。

6.3 keepalived双主脑裂:两台机器同时持有VIP

这是高可用架构里最危险的故障之一。正常情况下VIP只在一台Director上,主备通过VRRP组播报文沟通状态。如果出现过两台机器同时持有VIP的情况,客户端流量会被经常性地来回踢皮球,线上报障电话会被打爆。

我遇到过的一次脑裂原因很朴素:交换机的端口隔离把VRRP组播地址224.0.0.18给拦了,主备之间互相不知道对方还活着,各自都认为自己是Master,结果两台机器同时绑定VIP。

排查脑裂的方法:

# 在两台Director上都执行 ip addr show eth0 | grep 192.168.1.100

如果两台都出现了VIP,立刻检查:

  1. 防火墙是否放行VRRP协议(协议号112)。
  2. 交换机是否开启了组播过滤,224.0.0.18是否被屏蔽。
  3. 两台机器的virtual_router_idauth_pass是否一致。
  4. 两台机器的advert_int间隔是否一致。
  5. 主备的priority是否配置正确,不能相同。

预防措施是在交换机ACL里只允许合法的两台Director收发VRRP报文,配合监控定期检查VIP漂移状态。

6.4 健康检查误报导致RS反复抖动

TCP_CHECK只验证端口通不通,问题是很多故障是“端口通、请求超时”。后端Java应用做Full GC的时候,端口照常accept,但前端的业务请求已经处理不动了。这时候如果只靠TCP_CHECK判断健康,LVS会继续把流量分过去,造成部分请求延迟暴增。

生产环境的解决方案是用HTTP_GET探测业务健康接口。配置示例:

real_server 192.168.1.11 80 { weight 1 HTTP_GET { url { path /healthz status_code 200 } connect_timeout 3 nb_get_retry 3 delay_before_retry 1 } }

后端应用需要提供一个轻量的/healthz接口,只做最根本的存活检查。注意健康接口一定不能做重逻辑,比如连数据库、查缓存,否则后端一抖动,健康检查请求也会超时,导致大量RS被误摘。

另外,connect_timeoutnb_get_retry不要设置得太短。之前我把connect_timeout设为1秒,结果后端服务启动慢一点,健康检查就失败两三次,直接把刚启动的新RS摘掉,形成了一个“启动→被摘→再启动→再被摘”的循环。给检查器留一点容错余量,推荐3秒超时、重试3次。

6.5 内核参数和性能调优:大流量下的最后一道门

LVS转发本身很轻量,但高并发环境下内核参数的细节决定了你能扛住多少流量。

NAT模式必须开启转发:

net.ipv4.ip_forward = 1

加大TCP连接队列和SYN队列,应对突发连接:

net.core.somaxconn = 65535 net.ipv4.tcp_max_syn_backlog = 65535

开启LVS的SYN Proxy:

LVS可以承担一部分SYN Flood防御能力,原理是Director代替后端完成TCP三次握手,确认是真实客户端之后再把连接转发给RS。开启方式:

net.ipv4.vs.synproxy = 1

这个参数在遭受大量半连接攻击时非常有用,能让后端的cpu占用率稳定在一个很低的水平,而不是被SYN队列打爆。

谨慎处理TIME_WAIT:

网上很多教程教你把tcp_tw_reusetcp_tw_recycle都打开,但在有NAT的环境里开启tcp_tw_recycle会导致连接被随机重置,这是个大坑。我建议只开tcp_tw_reuse,配合长连接避免频繁创建连接,不要盲目抄参数。

在生产上线之前,强烈建议用压测工具打一轮流量,观察Director的CPU软中断和网卡丢包统计,把瓶颈在扩容前摸清楚。sar -n DEV 1可以看网卡PPS,mpstat -P ALL 1可以看软中断分布,这是压测时最常用的两个命令。

最后再分享一点个人心得。LVS是一个非常“老”的技术,老到很多新入行的同学觉得它过时了。但只要你在大流量环境待过就会发现,它凭借内核态转发和高稳定性,依然是很多头部互联网公司入口层的第一道门槛。面试也好、实际运维也罢,能把这个技术吃透的人,对“负载均衡”四个字的理解绝对比简历上泛泛写“熟悉Nginx”的人深一个层次。把这篇文章里的部署和排障流程过一遍,再遇到真实环境,你不会慌。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询