做了好几年负载均衡相关的工作,我越来越觉得 LVS DR 模式(Direct Routing)是四层负载均衡方案里最值得花时间吃透的那一个。它不像 NAT 模式那样所有流量都堆在入口,也不像 TUN 模式那样要额外维护隧道封装,却能在高并发场景下把吞吐、延迟和成本平衡得很舒服。这篇文章不是简单抄一遍 ipvsadm 命令,而是想把我理解的 Direct Routing 数据包流转过程、真实环境配置步骤、以及那些让我半夜爬起来查日志的坑,认认真真讲一遍。无论你是正在给后端集群搭入口,还是面试前想把 DR 模式说清楚,这篇内容应该都能派上用场。
1. 为什么是 DR:四层负载均衡方案的取舍与选型逻辑
1.1 LVS 的几种工作模式到底差在哪
LVS 本身有三种经典模式:NAT、TUN、DR,后来一些衍生方案里又看到过 FULLNAT。很多新手第一次接触这套东西,容易被“改 MAC、改 IP、隧道封装”这些词绕晕。我的习惯是先想清楚一个问题:这份流量到底谁来回?
NAT 模式下,Director 既要改写目标 IP,还要承担全部响应流量。哪怕后端 RS 已经把数据准备好了,也得原路返回给 Director,再由 Director 送回客户端。这意味着 Director 的网卡、CPU、连接表全都暴露在双向流量压力下,带宽很容易成为瓶颈。
TUN 模式则是把原始 IP 报文再包一层新的 IP 头,通过隧道送去后端的 RS。它的优势是可以跨越三层网络部署后端,但代价是每台 RS 都要支持隧道接口,并且 MTU、分片问题会时不时冒出来,排错成本并不低。
DR 模式走的是另一条路:Director 和所有 RS 在同一个二层广播域里,Director 收到客户端请求后,只改写数据帧里的目标 MAC 地址,IP 层完全不动,然后把帧从网卡扔出去。RS 拿到这个帧,发现目的 IP 是 VIP,本地恰好也有这个 VIP,于是像处理普通请求一样处理;响应包则由 RS 直接回给客户端,完全不经过 Director。
三种模式整理成表格会更清楚:
| 模式 | Director 改什么 | 响应包路径 | 后端要求 | 主要瓶颈 |
|---|---|---|---|---|
| NAT | 目标 IP/端口 | 必须回 Director | 可跨网段 | Director 双向流量 |
| TUN | IP 隧道封装 | RS 直达客户端 | 需隧道接口,可跨网段 | 封装开销、MTU |
| DR | 二层帧 MAC | RS 直达客户端 | 同二层广播域 | 无,但受二层范围限制 |
我自己在选型时,除非后端机器明确分布在多个机房,否则第一选择基本都是 DR。原因很朴素:它把“转发”这件事降到最低成本,后端只要会写应用,不需要理解复杂的隧道协议。
1.2 选 DR 之前要接受的三个限制
DR 模式不是没有代价。它之所以能这么轻量,是因为它把一个重要矛盾推给了网络设计:后端必须能直接响应客户端,并且必须和 Director 在同一个二层网络里。这个条件决定了三个限制。
第一,所有 RS 必须和 Director 处于同一个 VLAN 或者可二层互通的广播域。如果网络被划分成多个隔离网段,DR 默认就玩不转了。虽然通过策略路由、ARP 代理之类的手段也能做扩展,但那已经属于生产环境的特殊操作,不建议新手一上来就碰。
第二,后端 RS 必须自己持有 VIP,并且要保证不应该对外响应 VIP 的 ARP。这句话听起来矛盾,实际是 DR 模式最精髓的地方:VIP 必须存在于每台 RS 上,好让内核接收发往 VIP 的数据包;但同时这个 VIP 又不能“漏”到二层网络里,否则交换机的 ARP 表会把 VIP 对应的 MAC 学成多份,客户端请求就乱了。
第三,端口必须保持一致。Director 不能像 NAT 模式那样把 80 端口映射成 8080,因为请求到了 RS 之后,目标 IP 和端口都还是原来的值。如果 RS 上业务监听的是 8080,请求打过来访问 80 端口,RS 连接就建立不起来。
所以在立项的时候,我通常会先确认三件事:后端能不能直接上网?机房网络是不是同一个二层?业务端口能不能统一?只要这三个问题都能答“是”,DR 模式基本就是最优解。
2. Direct Routing 的数据包旅程:一次请求里藏着整个方案的秘密
2.1 从客户端到 Director,再到 Real Server 的完整路线
Direct Routing 这个名称很容易被误读成“直接路由转发”,其实它更接近“二层直连”的意思。为了把原理讲明白,我先给一套具体的 IP 规划:
- 客户端 CIP:198.51.100.50
- VIP:192.0.2.100
- Director 物理 IP:192.0.2.10
- RS1 IP:192.0.2.11
- RS2 IP:192.0.2.12
- 网关:192.0.2.1
一次完整的 HTTP 请求,数据包经历的过程大概是这样的:
客户端首先把 TCP SYN 发往 VIP 192.0.2.100:80。交换机通过 ARP 查询得知,VIP 对应的 MAC 是 Director 的网卡 MAC,于是这个帧进入 Director 的 eth0。Directro 的内核收到数据后,ip_vs 模块根据虚拟服务器规则选出一台 RS,比如 RS1。
关键动作发生在第二层:Director 把这个帧的目标 MAC 从自己的 MAC 改成 RS1 的 eth0 MAC,源 MAC 改成自己的 MAC,然后从 eth0 再扔出去。这个过程中,帧里的源 IP、目标 IP、TCP 端口全部都没有变。交换机看到目标 MAC 指向 RS1,于是把帧送到 RS1。
RS1 的 eth0 收到帧后,IP 层发现目标 IP 是 192.0.2.100,而本地 lo:0 接口上正好配了同一个地址,因此内核把它当作本机数据交给监听 80 端口的应用。应用处理完请求,生成响应报文,源 IP 自然就是 VIP 192.0.2.100。
那响应报文怎么回去?RS1 查路由表,发现目标 IP 198.51.100.50 不属于本地网段,于是走默认路由,通过网关 192.0.2.1 出去。整个响应过程不需要再绕回 Director。
这就是 DR 模式最让人舒服的地方:入站流量只决定“把请求引导给哪台机器”,出站流量全部由 RS 自己完成。
2.2 为什么这套模式能有这么高的吞吐
很多人把 LVS 叫作七层代理,这是不对的。LVS 的核心是一个四层连接转发表,它不终结 TCP 连接,也不解析 HTTP 内容。客户端和 RS 之间真正完成了 TCP 三次握手、数据传输、挥手全流程,Director 只是负责在关键节点上决定“这个数据包应该交给谁”。
我用一个生活化的类比来讲:Director 不是快递员,快递员是 RS 自己;Director 更像小区门口那个指路的保安,他不需要亲自帮每一户把快递搬上楼,他只需要知道每栋楼在哪个位置,然后告诉送快递的人往哪走。因为只做“指路”,Director 能扛的并发规模就远远高于那种既要接单又要派送的模式。
当然,这里也不是真的“指完路就再也不管”。LVS 会在内部维护一张连接转发表,记录五元组信息和选中的 RS。属于同一条连接的后缀数据包,到达 Director 后会被查表并继续转发给同一台 RS。所以严格说,入站方向的每个包都会经过 Director,只是 Director 不需要做复杂计算,工作量大为降低。
正因为如此,DR 模式特别适合那种“请求很小、响应很大”的业务,比如文件下载、图片加载、视频片段分发。入站可能只有几个 KB 的请求,回包却可能达到几十 MB,如果回包也要经过 Director,那瓶颈会非常明显。
2.3 只改 MAC 不改 IP,为什么这点很关键
理解 DR 模式,一个重要支点就是“为什么只改 MAC”。
如果 Director 把目标 IP 改成 RS 的物理 IP,那么 RS 响应时源 IP 就会变成物理 IP。客户端收到的响应来源不是 VIP,TCP 连接自然对不上,必须靠 NAT 再把源 IP 改回来,这就被迫把响应流量也拉回 Director 处理。一旦把目标 IP 改成 VIP,而 VIP 又存在每台 RS 上,那么 RS 可以用 VIP 作为响应源地址,客户端看起来就是一台稳定的服务器。
MAC 地址的作用范围只在二层网络。Director 和 RS 处于同一个广播域时,通过改写目标 MAC 就能把帧送到指定主机。这个过程不需要修改 IP 报文,避免了 NAT 带来的性能消耗,也避免隧道封装带来的额外协议头。
简单总结就是:改 MAC 是为了在“同一个二层网络内”完成导流,不改 IP 是为了让“RS 能以自己的 VIP 身份直接回包”。这两个条件缺一不可,也正好解释了 DR 模式为什么要依赖二层互通的网络结构。
3. 从零搭一套 DR 共享网段实验环境
3.1 网络拓扑和 IP 规划
纸上谈兵不如动手。下面的实验环境是我在本地用虚拟机常搭的一套结构,三台机器都跑在同一个虚拟交换机上,模拟生产环境里一个普通 VLAN:
- Director:eth0 为 192.0.2.10/24,负责承载 VIP 192.0.2.100/24,并担任 LVS 转发节点
- RS1:eth0 为 192.0.2.11/24,业务监听 80 端口
- RS2:eth0 为 192.0.2.12/24,业务监听 80 端口
- 网关:192.0.2.1,负责把出网流量带走
有一点要特别交代:VIP 不要配在交换机上,它只是一台或多台 Director 网卡上的逻辑地址。实验里也不用做 VLAN 隔离,所有机器都在同一个子网即可。
我在规划阶段最想强调的其实是反向思考:VIP 应该看成“谁提供服务谁持有”的地址。Director 持有它是为了对外接收请求,RS 持有它则是为了能以内核认可的方式接收转发过来的请求。两边都要有 VIP,但两边对 ARP 的响应策略完全不同。
3.2 准备三台机器与基础检查
机器我建议用最小化安装的 Linux 系统,版本新一点没关系,关键是内核要支持 IPVS。现在主流发行版默认都带了 ip_vs 模块,只是不一定自动加载。开始操作前,先把模块抓出来看看:
modprobe ip_vs lsmod | grep ip_vs如果 lsmod 输出里有 ip_vs 相关的行,说明内核模块已经就绪。如果找不到,优先检查是不是内核没有加载模块,或者包管理工具里有没有 ipvsadm 和 keepalived。
RHEL 系的话直接装:
yum install -y ipvsadm keepalivedDebian 系对应的是:
apt install -y ipvsadm keepalived装完之后,先把三台机器的网络都调通。至少要做三件事:确认 eth0 都获得了规划好的 IP、确认彼此之间能 ping 通、确认默认路由都指向 192.0.2.1。很多 DR 问题最后查出来都是默认路由不对,这一步不能省。
检查命令很简单:
ip addr ip route ping -c 3 192.0.2.11 ping -c 3 192.0.2.123.3 需要提前确认的路由与转发问题
Director 要负责转发数据包,第一个要开的系统参数是 ip_forward:
sysctl -w net.ipv4.ip_forward=1如果不开启这个参数,Director 收到目标是 VIP 的包之后,即使 IPVS 规则存在,也可能不会继续往 RS 送。这属于底层转发行为,不是 IPVS 自己就能覆盖的。
第二个要关注的是反向路径过滤。Linux 内核默认可能有 rp_filter 保护,用来防止源地址伪造攻击。但在 LVS DR 场景下,数据包从 eth0 进入,源 IP 是客户端地址,反向查路由可能会因为路由表不够“对称”而丢包。我在不少内核版本上遇到过这种情况,建议实验阶段先把相关过滤关掉,避免它干扰排错:
sysctl -w net.ipv4.conf.all.rp_filter=0 sysctl -w net.ipv4.conf.eth0.rp_filter=0第三个要注意的是,RS 的默认路由必须保留。很多人看完 DR 的原理,误以为响应包只要从 lo 口出去就行,于是把默认路由改到 lo 上,结果机器直接失去和外界的通信。RS 的默认路由必须指向真实网关,出网流量要能从 eth0 出去,这一点后面细说。
4. Director 与 Real Server 的配置落地:照着敲就能跑通
4.1 Director 侧:让内核和 ipvsadm 进入工作状态
Director 上的配置分两层:一层是网络地址,一层是 IPVS 规则。
先配置 VIP。我习惯用 ip 命令直接操作,快速验证时最方便:
ip addr add 192.0.2.100/24 dev eth0 label eth0:0这个命令会在 eth0 上叠加一个别名接口 eth0:0,地址是 192.0.2.100。配置完成后,Director 才会对这个地址回应 ARP,交换机也才能学会 VIP 对应 Director 的 MAC。
接着添加 LVS 虚拟服务。以 HTTP 为例,使用加权轮询算法:
ipvsadm -A -t 192.0.2.100:80 -s wrr ipvsadm -a -t 192.0.2.100:80 -r 192.0.2.11:80 -g -w 1 ipvsadm -a -t 192.0.2.100:80 -r 192.0.2.12:80 -g -w 1第一条创建虚拟服务,第二条和第三条把两台 RS 加入服务组。-g表示使用 DR 模式,-w是指定权重。如果这里忘了写-g,默认可能进入 NAT 模式,那响应路径就完全不是 DR 了。
查看规则和统计信息:
ipvsadm -L -n --stats ipvsadm -L -n --rate如果--stats里的 InBytes 和 OutBytes 都在涨,说明转发已经开始工作。不过要注意,DR 模式下 OutBytes 通常很小,因为响应流量不经过 Director。
如果只做临时验证,这些命令就够了。正式环境一般会配合 Keepalived,规则由 Keepalived 动态下发,而不是直接写在 ipvsadm 里。
4.2 RS 侧:lo:0、ARP 抑制、默认路由缺一不可
RS 的配置是 DR 模式最容易出问题的地方。少了任何一环,连接都可能建立不起来。
先把 VIP 放到回环接口上。注意这里用的是 /32:
ip addr add 192.0.2.100/32 dev lo label lo:0为什么不用 /24?因为 RS 上的 VIP 只是一个“让内核认为这是本机地址”的标志,它不需要参与广播域里的网络段计算。配成 /32 最干净,避免路由表各种奇奇怪怪的问题。
然后配置 ARP 抑制。这是最关键的一步,也是很多新手最懵的一步。RS 上有 VIP,但对外不能抢答 VIP 的 ARP 请求,否则邻居会认为 VIP 同时存在于多台机器。标准参数是:
sysctl -w net.ipv4.conf.all.arp_ignore=1 sysctl -w net.ipv4.conf.all.arp_announce=2 sysctl -w net.ipv4.conf.lo.arp_ignore=1 sysctl -w net.ipv4.conf.lo.arp_announce=2 sysctl -w net.ipv4.conf.eth0.arp_ignore=1 sysctl -w net.ipv4.conf.eth0.arp_announce=2arp_ignore=1的意思是不再对所有“目标 IP 等于本地任意接口地址”的 ARP 请求都回复,而只回复目标 IP 正好属于请求网络接口的那个地址。RS 的 eth0 上没有 VIP,所以外界询问 VIP 时,RS 保持沉默。
arp_announce=2的意思是让本机在对外发送 ARP 通告时,尽量使用最合适的本地 IP 作为源地址,避免把 lo:0 上的 VIP 当作源地址通告出去。这一条在 RS 需要对外主动发送报文时特别重要。
为了保险,还可以顺手关闭反向路径过滤:
sysctl -w net.ipv4.conf.all.rp_filter=0 sysctl -w net.ipv4.conf.eth0.rp_filter=0再把 eth0 的默认路由确认一遍:
ip route add default via 192.0.2.1 dev eth0最后启动业务进程。监听地址可以写 0.0.0.0:80,也可以写 192.0.2.100:80。如果写后者,一定要确保 VIP 已经配置在 lo:0 上,否则服务根本起不来。
4.3 验证链路:用 ipvsadm 和 tcpdump 确认转发路径
配置全做完,不要急着欢呼。先做个端到端验证:在客户端持续访问 VIP,然后在 Director、RS 上分别抓包对比路径。
客户端可以用一个持续请求:
curl http://192.0.2.100/在 RS 上抓包,应该能看到来自 Director 转发过来的请求包,以及本机回给客户端的响应包:
tcpdump -ni eth0 tcp port 80在 Director 上抓包,正常情况下只能看到客户端发往 VIP 的入站请求,响应方向的包不应该出现。如果 Director 同时抓到大量响应包,说明网络里可能发生了路径回流,或者 RS 配置有问题,响应被错误地送回了 Director。
再回到 Director 上查看连接状态:
ipvsadm -L -n -c这里能看到活跃的连接记录,每一行都记录着客户端 IP、VIP、RS IP 以及连接状态。看到这些条目不断出现、消失、再出现,基本可以确认数据通路是通畅的。
5. 我踩过的 DR 模式生产坑:ARP、默认路由和长连接
5.1 ARP 通杀问题:VIP 出现在所有 RS 上的后果
DR 配置里最阴险的坑,就是 ARP 通杀。
有些文章为了省事,只让你在 RS 上加sysctl -w net.ipv4.conf.all.arp_ignore=1,没有让你同时配置具体接口。我在生产环境里遇到过这么一次:客户端访问 VIP,时通时不通,大概每三五次请求就有一次超时。一开始怀疑后端服务不稳定,后来发现问题是所有 RS 都对 VIP 的 ARP 请求作了应答。
因为 VIP 配置在每台 RS 的 lo:0 上,如果不限制 ARP 响应规则,Linux 会把这个地址当作“本机拥有的地址”来响应整个二层网络的 ARP 请求。于是交换机的 ARP 表里,192.0.2.100 一会儿对应 Director 的 MAC,一会儿对应 RS1 的 MAC,一会儿又变成 RS2 的 MAC。客户端发出去的报文,可能被交换机随机送到任意一台机器,而只有 Director 上的 IPVS 才知道怎么转发,其他机器收到后自然就是黑洞。
解决起来不算复杂,就是把我前面写的那几条 sysctl 参数全部配置到位,特别是接口级的conf.lo和conf.eth0也要一起写。配置改完后,最好在两台 RS 上分别执行:
ip neigh flush all同时清掉交换机的动态 ARP 缓存。如果交换机可以重启接口,也会加速收敛。
另外提醒一句:不要试图用防火墙把 RS 的 ARP 请求挡掉,ARP 是二层协议,iptables 对它的拦截非常有限。与其折腾防火墙,不如老老实实配好 sysctl。
5.2 RS 上的默认路由不能乱来
第二个大坑是路由。我见过有人在 RS 上执行了这样一条命令:
ip route add default dev lo这人以为“DR 模式下响应包要从 lo 走到 VIP”,结果整台 RS 的所有出网流量都走回环接口,TCP 三次握手的 SYN 都能收到,但响应包永远送不出去。客户端表现就是连接一直卡在握手状态,超时后失败。
理解这个坑之前,要先分清两个概念:VIP 放在 lo:0 上,是为了让内核识别“这个 IP 是本机的”,而不是为了让流量从 lo 出去。真正要出去的流量,必须经过 eth0 和网关。
所以 RS 上的路由表,至少应该有两条核心路由:一条是 eth0 对应的网段路由,另一条就是默认路由default via 192.0.2.1 dev eth0。如果因为某些自动化脚本把默认路由改坏了,立刻改回来即可:
ip route replace default via 192.0.2.1 dev eth0还有一种容易被忽略的情况:RS 上如果配置了多块网卡,源地址选择可能会踩到策略路由的问题。DR 模式下,我习惯把业务网卡和其他管理网卡分开,并用ip rule明确主备关系,但新手阶段先不要引入太多策略路由,保持一张网卡、一条默认路由最不容易出错。
5.3 调度算法、会话保持和长连接超时
LVS 支持的调度算法不少,但不是越复杂越好。我自己的选型经验是:
| 算法 | 适合场景 |
|---|---|
| rr | RS 配置完全一致,请求成本均匀 |
| wrr | RS 配置有差异,需要按权重分配 |
| wlc | 长连接多、连接存活时间差异大的场景 |
| sh | 希望同一个来源 IP 始终打到同一台 RS |
wlc 全称是 Weighted Least Connections,它会把新请求优先分配给当前活跃连接数最少的 RS。后端连接处理时间差异大的业务,用 wlc 效果往往比轮询好。但如果是无状态短连接、RS 性能又一致,rr 和 wrr 足够。
会话保持方面,如果业务自身不依赖 session,尽量别开持久连接;因为持久连接会让某个来源 IP 的请求长时间固定在一台 RS 上,导致负载不均。如果必须开,用ipvsadm -p指定超时时间,比如保持 10 分钟:
ipvsadm -E -t 192.0.2.100:80 -s rr -p 600或者添加规则时直接带上-p 600。
另一个很容易踩的坑是 LVS 自身的 TCP 连接表超时。默认配置下,TCP 空闲连接超过一定时间后,LVS 会认为连接已经结束,把连接表里的记录回收。如果客户端和后端 RS 之间有一条还活着的长连接,但长时间没有数据传输,下一个数据包到来时 LVS 可能把它当成新连接调度到另一台 RS,而旧 RS 上根本没有这个 TCP 连接,于是连接被重置。
碰到这种业务,可以手动调大超时时间。比如把 TCP 连接超时改到 1 小时:
ipvsadm --set 3600 120 300这条命令分别设置 TCP、TCP FIN、UDP 的超时秒数。调整完之后,长连接就不容易被 LVS 半路“遗忘”了。
如果你同时在使用 Keepalived 管理 IPVS,需要注意 Keepalived 启动时可能会重置部分 IPVS 规则,超时参数最好在 Keepalived 配置里也体现,或者在业务真正起来后再执行ipvsadm --set,确保规则生效。
6. 结合 Keepalived 做高可用:DR 模式下的实践配置
6.1 Keepalived 如何接管 VIP 和虚拟服务器
单台 Director 做得再好,也存在单点风险。生产环境里我通常用两台 Director 配合 Keepalived,组成一主一备,靠 VRRP 协议实现 VIP 漂移。
Keepalived 的配置分成两段:一段负责 VRRP,一段负责 IPVS 虚拟服务器。主节点配置大致如下:
global_defs { router_id LVS_DR_MASTER } vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1234 } virtual_ipaddress { 192.0.2.100/24 dev eth0 label eth0:0 } } virtual_server 192.0.2.100 80 { delay_loop 6 lb_algo wrr lb_kind DR persistence_timeout 60 protocol TCP real_server 192.0.2.11 80 { weight 1 TCP_CHECK { connect_port 80 connect_timeout 3 retry 3 } } real_server 192.0.2.12 80 { weight 2 TCP_CHECK { connect_port 80 connect_timeout 3 retry 3 } } }备用节点只需要把state改成BACKUP,priority改低,并在global_defs里换一个router_id,其他内容保持一致。VRRP 会在主节点故障后,让备用节点接管 VIP 并发送免费 ARP,把交换机里 VIP 对应的 MAC 更新到备用 Director 的网卡。
需要注意auth_pass在 Keepalived 的配置里不要设置太复杂的特殊字符,两台机器必须完全一致,否则 VRRP 包可能验证失败。
很多人会问:既然 Keepalived 能自动管理 IPVS,那第 4 节里手动敲的 ipvsadm 还需要吗?我的建议是:先手动搭一遍,确认网络和转发逻辑没问题,再交给 Keepalived 接手。因为如果一开始就自动化配置,出现问题时反而不知道是网络问题还是配置问题。
6.2 故障切换时 RS 侧要不要跟着改
这个问题经常有人搞混。Keepalived 接管的是 Director 上的 VIP,不是 RS 上的 VIP。RS 的 lo:0 上依然保留着 192.0.2.100,不管主备 Director 怎么切换,RS 都不需要改任何配置。
原因就在于 ARP 抑制参数。RS 上的 VIP 虽然存在,但对外不响应 VIP 的 ARP 请求。整个二层网络里,只有当前处于 MASTER 状态的 Director 会响应这个 VIP 的 ARP。主备切换后,新 MASTER 发出免费 ARP,交换机的 MAC 表随之更新,客户端感知不到任何变化。
所以这里有一个硬性禁止:绝对不要为了“高可用”而把 VIP 配置到 RS 的 eth0 上。如果 VIP 出现在 RS 的物理接口上,即使配置了 ARP 抑制,也无法完全保证交换机的 ARP 学习行为符合预期。最稳妥的做法就是让 VIP 只出现在 Director 的 eth0 别名和 RS 的 lo 别名上,中间不要有任何混淆。
6.3 健康检查还要注意什么
Keepalived 默认的 TCP_CHECK 只能确认 TCP 端口能连上,但它不能判断业务是否真的可用。比如后端服务卡死,端口还能 accept,但 HTTP 请求已经 5 秒不回,这时 TCP_CHECK 依然会判断节点健康。
生产环境我见过两种做法。一种是在 real_server 里配置 HTTP_GET 检查,让 Keepalived 定期请求一个固定 URL,通过响应状态码判断服务是否真正可用。这个方法更贴近用户视角,但配置稍微复杂,要注意请求超时不要影响业务本身。
另一种做法是保留 TCP_CHECK 作为兜底,同时在外面加一层独立的拨测系统,定时请求 VIP 上的业务 URL,发现异常就告警。这两种方式我建议至少有一个,毕竟 LVS 只能保证“流量转发到了”,不保证“转发到了之后应用一定没问题”。
回到我自己的实践,每套 DR 高可用环境验收时都会做三件事:先临时把备用 Director 停掉,确认 VIP 能快速回切到主节点;再临时把主 Director 的网卡断掉,确认备用节点能接管且业务无损;最后把所有 RS 的 lo:0 临时去掉,确认 VIP 的 ARP 只会由 Director 响应,不会存在多 IP 多 MAC 的混乱情况。
经历过几次线上故障之后,我现在再看 DR 模式,心态已经比较坦然。它确实高效,但高效不等于无脑。只要遵循“VIP 归属清晰、ARP 响应收敛、默认路由可靠”这几条原则,绝大多数诡异问题都能提前规避。希望这篇从一个运维和开发双视角写下来的实践记录,也能帮你少走一条弯路。