
LVS 快过 Nginx:负载均衡长在内核里
LVS 快过 Nginx:负载均衡长在内核里
聊负载均衡,大多数人张口就是 Nginx。但往流量入口再退一层,有个更老、更快的东西:LVS(Linux Virtual Server)——章文嵩博士 1998 年发起的项目,如今是 Linux 内核的标准组件。
它快的道理一句话讲完:Nginx 是用户态进程,收包、解析、再发包,一个请求两次穿越内核/用户态边界;LVS 的转发代码(ipvs 模块)就挂在内核的 INPUT 链上,数据包还没到用户态就被改写转走了。没有进程切换,没有 socket,没有代理。
你不用替换 Nginx——绝大多数大厂的入口是 LVS 在前做四层分发、Nginx 在后做七层。但要理解入口层为什么这么设计,得先看懂 LVS。
请求在内核里拐了个弯
整个转发链路长这样:
五个术语先立住:DS(调度器)、RS(真实服务器)、VIP(对外服务 IP)、DIP(DS 内网 IP)、RIP(后端 IP)。LVS 的所有玩法,都是围绕这五个 IP 做文章。
有个细节值得停一下:ipvs 不在 PREROUTING 也不在 POSTROUTING,它挂在 INPUT 链上——请求"到达本机"但没进任何进程,就被劫持转走了。这是它比一切用户态代理快一档的根本原因。
你本机就能验证这件事,两条命令:
sudo modprobe ip_vs
cat /proc/net/ip_vs第一行把模块装进内核,第二行读它的连接表——LVS 干活的证据就躺在 proc 文件系统里,不在任何进程里。
四种模式:只看一个问题——响应回不回调度器
LVS 有四种转发模式,新手容易被名字绕晕(NAT/DR/TUN/FullNAT)。其实四种模式的差异,全部由一个问题决定:响应报文走不走调度器。
NAT:响应回来,调度器是必经之路。 请求改目标 IP 转给 RS,响应改源 IP 送回客户端,一来一回都过 DS。代价是 DIP 和 RIP 必须同网段、RS 网关必须指向 DIP;换来的是 RS 可以用任意操作系统、支持端口映射——约束最宽松,性能上限最低。
DR:响应直接走,调度器只看请求。 不改 IP 改 MAC——DS 和 RS 同一个二层网络,包直接送进 RS 的网卡;RS 处理完,以 VIP 为源地址直接回客户端。请求过 DS、响应不过,这就是 DR 吞吐最高的原因。代价:必须同机房、不支持端口映射,而且 RS 的 lo 上要配 VIP。
TUN:隧道跨机房。 原始 IP 包外面套一层新 IP 头(DIP→RIP),跨三层网络送到远端 RS,RS 拆壳处理完同样直接回客户端。响应不经 DS,同 DR;区别是能跨机房,代价是所有 IP 要公网地址、RS 必须支持隧道。
FullNAT:NAT 的增强版(阿里加的内核特性)。 把 CIP→VIP 完整转换成 LIP→RIP 两个内网地址,从而跨 VLAN。进出全过 LVS,文档建议上万兆网卡。
| 响应过 DS | RS 网关 | 部署范围 | 端口映射 | RS 系统 | |
|---|---|---|---|---|---|
| NAT | ✅ | 指向 DIP | 同网段 | ✅ | 任意 |
| FullNAT | ✅ | — | 跨 VLAN | ✅ | 任意 |
| DR | ❌ | 禁止指向 DIP | 同机房二层 | ❌ | 大多数 |
| TUN | ❌ | 不可能 | 跨机房 | ❌ | 支持隧道 |
选型就一句话:一般规模用 DR;跨机房用 TUN;RS 异构或要端口映射,忍痛 NAT;大规模多 VLAN 上 FullNAT。
三条踩过才知道的铁律
1. 裸 LVS 没有健康检查。 RS 挂了,ipvs 照样把请求往尸体上送——这是它最大的坑,不是配置优化项,是必配项。Keepalived 的 TCP_CHECK 补上这块:探活失败摘除 RS,恢复自动加回。
2. DR 的 ARP 坑是静默的。 RS 的 lo 上配了 VIP 之后,必须压住 RS 别应答 VIP 的 ARP(arp_ignore=1、arp_announce=2 四行内核参数,一个不能少)。配错不报错,症状是"负载看起来不均"——实际是交换机学到了"VIP 在某台 RS 上",流量绕过调度器直接命中它,负载均衡整个失效。排查手段:在 RS 上抓 VIP 的 ARP 包。
3. NAT 模式记得关 send_redirects。 不关的话内核会发 ICMP 重定向,教客户端直连 RS——等于亲手把调度器架空。
番外:调度算法不用背
八种算法按"看不看连接数"分两组记就行:静态四种(rr 轮询 / wrr 加权 / dh、sh 散列做会话保持),动态四种(lc、wlc 加权最少连接——生产默认选它、lblc、lblcr)。换算法就是改一行 -s wrr 到 -s wlc,规则重载即生效——算法是配置,不是代码。
收个尾
LVS 的全部魔法:在内核 INPUT 链上拦下发往 VIP 的包,改写或封装后扔给真实服务器。四种模式只看"响应回不回调度器"。铁律两条:Keepalived 必配,DR 的 ARP 参数四行一个不能少。
参考:xgfone/snippet《LVS 负载均衡原理及安装配置详解》、linuxvirtualserver.org。老文档命令是 ifconfig 时代的,systemd 机器上要翻译成 ip/nmcli,原理不过时,命令别照抄。
聊两句:你们生产环境的入口层是 Nginx 直接扛,还是前面挂了 LVS / 云 SLB?如果用过 DR 模式,ARP 那个坑你是怎么发现的——我猜一半人是负载不均了才回头查的。评论区说说,我会置顶一条我的判断。
下一篇拆「云端模型只想、本地模型干活」的双模型协同流水线,省 API 账单的实战架构,关注不迷路。
