文章目录
- 一、集群与分布式基础
- 1.1 系统性能扩展方式
- 1.2 集群的三种类型
- 1.3 集群 vs 分布式——面试高频题
- 二、LVS 架构原理
- 2.1 LVS 是什么
- 2.2 核心概念:五个 IP
- 2.3 四种工作模式——LVS 的精华
- NAT 模式
- DR 模式(直接路由)
- TUN 模式(隧道)
- FullNAT 模式
- 四种模式总结
- 三、调度算法详解
- 3.1 静态调度算法
- 3.2 动态调度算法
- 3.3 内核 4.15+ 新增的两个算法
- 四、NAT 模式实战
- 4.1 实验环境
- 4.2 逐步配置
- 4.3 改为加权轮询
- 4.4 规则持久化
- 五、DR 模式实战
- 5.1 实验拓扑
- 5.2 核心难题:ARP 抑制
- 5.3 调度器配置
- 5.4 NAT vs DR 实战心得
- 六、防火墙标记(FWM)——多端口的救星
- 6.1 问题的本质
- 6.2 解决方案
- 七、持久连接——让用户不掉线
- 7.1 问题场景
- 7.2 LVS 的持久连接方案
- 八、LVS + Keepalived 高可用概述
- 8.1 问题来了
- 8.2 Keepalived 怎么解决
- 九、ipvsadm 命令速查
- 集群服务管理
- RS 管理
- 查看 & 调试
- 关键文件
- 总结:学习心得
这篇文章是 LVS 负载均衡的完整学习笔记。从为什么需要集群开始,到四种工作模式的底层原理,再到亲手搭建 NAT 和 DR 模式的全过程,以及踩过的坑和总结的经验。希望能帮你建立起对 LVS 的系统认知。
一、集群与分布式基础
1.1 系统性能扩展方式
在学习 LVS 之前,先想清楚一个问题:当一台服务器扛不住流量了,怎么办?
答案只有两个方向:
- Scale UP(向上扩展):给服务器加配置——换更强的 CPU、加更多内存、上 SSD。这就像给一个人吃更多蛋白粉让他变得更强壮。简单粗暴,但问题是:物理上限摆在那里,你不可能无限加;而且越往上走,同样性能提升的成本是指数级增长的。一台 128 核的服务器,价格可能是 4 台 32 核的 5 倍以上。
- Scale Out(向外扩展):买更多服务器,用集群技术把它们组合起来对外提供服务。这就像不指望一个超人干所有活,而是雇一群人分工协作。单台配置不用很高,但整体能力可以线性增长。这也是互联网公司的主流选择——用廉价机器堆出高可用。
LVS 正是 Scale Out 模式下最经典的负载均衡方案。它不是跑在应用层的,而是直接跑在 Linux 内核里,所以性能极高、几乎不消耗资源。理解了这个大背景,后面学起来才有方向感。
1.2 集群的三种类型
集群(Cluster)说起来就是把多台机器绑在一起用,但其实有三种完全不同的目的:
| 类型 | 核心目标 | 一句话理解 | 典型实现 |
|---|---|---|---|
| LB(负载均衡) | 分散流量 | 一个人忙不过来,多找几个人一起干 | Nginx、HAProxy、LVS |
| HA(高可用) | 消除单点故障 | 主力挂了备胎立刻顶上 | Keepalived、Pacemaker |
| HPC(高性能计算) | 并行计算 | 把一个大任务拆成小任务同时算 | 超算中心 |
小结:实际生产环境中,LB 和 HA 往往是配合使用的。比如一个典型的架构:两台 LVS 调度器通过 Keepalived 做 HA(一主一备),下面挂着一堆 Nginx 做七层反向代理(LB),再后面才是真正跑业务的应用服务器。每一层都在用集群解决自己的问题。
关于高可用有几个关键指标值得关注:
- MTBF(Mean Time Between Failure):平均多久出一次故障——越长越好
- MTTR(Mean Time To Restoration):出故障后平均多久能恢复——越短越好
- 可用性= MTBF / (MTBF + MTTR):比如一年出一次故障、每次 1 小时恢复,可用性 ≈ 99.99%(四个九)
- SLA(Service Level Agreement):这是跟客户/老板签的服务协议,达不到就挨罚。运维的核心 KPI 就是这个。
💡 一个容易被忽略的点:计划内停机(比如发版重启)也计入 SLA。所以真正的高可用架构必须支持滚动发布,不能停服升级。
1.3 集群 vs 分布式——面试高频题
这两个概念刚开始学很容易搞混,整理了一个对比:
| 维度 | 集群(Cluster) | 分布式(Distributed) |
|---|---|---|
| 核心逻辑 | 同一个活,多个人一起干 | 不同的活,每人负责一部分 |
| 每台机器 | 代码和数据都一样 | 代码和数据不一样,合起来才完整 |
| 提升什么 | 单位时间内能处理更多请求(吞吐量) | 单个请求处理更快(响应速度) |
| 挂了怎么办 | 一台挂了其他顶上,服务不受影响 | 一个节点挂了,它负责的那部分功能就废了 |
打个比方:集群像快餐店的 3 个收银员——干的活一模一样,一个请假了还有两个顶着。分布式像一条流水线——切菜的、炒菜的、打包的各管各的,切菜的走了整条线就停了。
大型网站的经典架构:前端LVS(四层集群)→ 中间Nginx 集群(七层)→ 后端应用服务器集群。每一层都是集群,但层与层之间又是分布式的协作关系。
二、LVS 架构原理
2.1 LVS 是什么
LVS(Linux Virtual Server)是 Linux 内核里自带的负载均衡模块,由中国人章文嵩博士在 1998 年开发,后来被收入了 Linux 内核标准主线。值得一提——全球无数服务器跑着的四层负载均衡,核心代码是中国人写的。
阿里云的四层 SLB(Server Load Balancer)底层就是LVS + Keepalived。你如果在阿里云买过 SLB,其实就是在用 LVS。
几个核心组件的关系:
ip_vs:内核模块,真正干活的——截获数据包、查表、改包头、转发。运行在内核态。ipvsadm:用户空间的命令行工具,用来给内核模块下发规则。类似 iptables 和 netfilter 的关系。/proc/net/ip_vs:内核暴露的 proc 文件,可以 cat 出来看当前有哪些调度规则。/proc/net/ip_vs_conn:当前所有活跃连接的表,排查问题时非常有用。
小结:LVS 本质上就是一个内核级的数据包转发器。它不看 HTTP Header,不管 URL 是什么,只管 IP 和端口——所以叫"四层负载均衡"。也是因为它工作在内核态、只做最简单的包头修改,所以性能可以达到线速转发,比 Nginx 这种跑在用户态的七层代理快一个数量级。
2.2 核心概念:五个 IP
这五个概念贯穿整个 LVS 学习过程,必须记牢:
| 缩写 | 全称 | 在哪个设备上 | 一句话 |
|---|---|---|---|
| CIP | Client IP | 客户端 | 发起请求的真实用户 IP |
| VIP | Virtual Server IP | 调度器(对外) | 对外暴露的地址,客户端访问这个 |
| DIP | Director IP | 调度器(对内) | 调度器和后端 RS 通信用的内网 IP |
| RIP | Real Server IP | 真实服务器 | 真正处理请求的后端服务器 IP |
| VS | Virtual Server | 调度器 | 整个调度系统的"大脑" |
数据包怎么走的?
CIP ←→ VIP == DIP ←→ RIP客户端只认识 VIP,RS 只认识 DIP。调度器在中间做"翻译"——这里面最核心的就是怎么把发给 VIP 的包,变个方式交给 RIP。四种工作模式的区别,归根结底就是翻译方式不同。
2.3 四种工作模式——LVS 的精华
这是 LVS 最难但也最重要的部分。需要花时间才真正理解每种模式的数据流。
NAT 模式
本质:多目标 IP 的 DNAT。调度器把请求包里的目标地址从 VIP 改成 RIP,然后把 RS 回包里的源地址从 RIP 改回 VIP。
客户端 → VS → RS(改目标IP) RS → VS → 客户端(改源IP)小结:NAT 模式最好理解——调度器就像一个"翻译官",请求进来翻译一遍,响应出去再翻译一遍。优点是可以做端口映射(比如 VIP:80 → RIP:8080),缺点是进出都要经过调度器,当后端 RS 多了以后,调度器自己会成为瓶颈。
⚠️ 重要:RS 的网关必须指向 DIP,否则 RS 回包不经过调度器,调度器没法把源 IP 从 RIP 改回 VIP,客户端收到一个不认识的回包就直接丢了。
DR 模式(直接路由)
本质:不碰 IP 层,只改 MAC 地址。调度器把请求包的目标 MAC从自己的 MAC 改成某台 RS 的 MAC,然后原样扔到交换机上。
客户端 → VS(改目标MAC为RS的MAC)→ RS RS → 客户端(直接回,不经过VS)小结:DR 模式是 LVS 的精髓。关键洞察:响应流量通常比请求流量大得多(用户请求一个几十字节的 URL,服务器回一个几 MB 的页面),所以让响应直接回客户端、不经过调度器,调度器的吞吐能力就释放出来了。
但也带来了一个问题:RS 必须也有 VIP(否则 RS 收到的包目标 IP=VIP,而 RS 自己的 IP=RIP,会直接丢弃)。既然 RS 也有 VIP,那就又有个新问题:客户端发 ARP 问"谁有 VIP?“的时候,调度器和所有 RS 都会回答"在这!”——这就乱套了。所以必须让 RS抑制 ARP 响应,后面实战部分会详细讲怎么做。
TUN 模式(隧道)
本质:在原 IP 包外面再套一层 IP 头。外层:DIP→RIP(用来在网络上路由),内层:CIP→VIP(原封不动)。
小结:TUN 模式的核心价值是可以跨网络。DR 要求调度器和 RS 在同一个二层网络,但 TUN 不需要——只要 IP 能通就行。所以它适合做异地负载均衡。代价是 RS 必须支持 IPIP 隧道协议。
FullNAT 模式
本质:同时改源 IP 和目标 IP。CIP→DIP、VIP→RIP。
这个模式是淘宝/阿里内部开发使用的,解决了一个问题:RS 看到的源 IP 是 DIP 而不是真实客户端 IP。好处是 RS 不需要特殊配置,坏处是 RS 日志里全是 DIP,排查问题很麻烦。
⚠️ FullNAT 需要给内核打补丁,主线内核不支持。一般除非你在阿里云上做深度定制,否则用不到。
四种模式总结
| 特性 | NAT | DR | TUN | FullNAT |
|---|---|---|---|---|
| RS 要求 | 无 | 需禁 ARP | 需支持隧道 | 无 |
| 跨网段 | ✅ | ❌ | ✅ | ✅ |
| 端口映射 | ✅ | ❌ | ❌ | ✅ |
| 回包经调度器 | 是(压力大) | 否(压力小) | 否 | 是 |
| 推荐场景 | 小规模/异构环境 | 主力方案 | 异地容灾 | 阿里内部 |
选择建议:绝大多数场景直接用 DR。除非 RS 是 Windows(不好配 ARP 抑制)、或者需要做端口映射,才考虑 NAT。TUN 和 FullNAT 属于进阶场景。
三、调度算法详解
ipvs 的调度算法核心分两类:静态(不考虑 RS 实时负载,纯算法)和动态(根据 RS 当前连接数等指标来判断)。
3.1 静态调度算法
| 算法 | 逻辑 | 什么时候用 |
|---|---|---|
| RR(轮询) | 1→2→3→1→2→3…依次来 | RS 配置完全相同时用 |
| WRR(加权轮询) | 按权重比例分配 | RS 配置不同时(比如一台 8C 一台 4C,权重 2:1) |
| SH(源地址哈希) | 同一客户端 IP → 同一 RS | 需要会话保持但又不想用持久连接 |
| DH(目标地址哈希) | 同一目标 URL → 同一 RS | 正向代理缓存场景,比如运营商缓存 |
小结:RR 和 WRR 是最基础也最常用的。但要注意,RR 在 RS 性能差异大时会出问题——性能差的机器被分配同样多的请求,响应变慢,拖垮整体体验。所以实际生产中,"加权"几乎是一个必选项,哪怕所有 RS 配置相同也设一样的权重,至少保留以后调整的灵活性。
SH 算法听起来很美好,但它有个致命缺点:如果某个客户端 IP 后面其实是一个 NAT 网关(比如公司的出口 IP),那成百上千个不同用户都会被哈希到同一台 RS,导致负载严重不均衡。
3.2 动态调度算法
这是 LVS 真正智能的地方——它不仅看算法,还看每台 RS 的实时负载:
| 算法 | 核心逻辑 | 适用场景 |
|---|---|---|
| LC(最少连接) | 谁连接少调度给谁 | 长连接场景(数据库代理、WebSocket) |
| WLC(加权最少连接) | LC + 权重修正,默认算法 | 通用场景,最推荐 |
| SED(最短预期延迟) | 初始阶段高权重优先 | 权重差异大时避免低权重机器饿死 |
| NQ(永不排队) | 第一轮每人一个,之后 SED | 避免第一波请求全砸到高权重 RS |
| LBLC(本地最少连接) | 动态 DH + 负载感知 | 正向代理 |
| LBLCR(带复制的 LBLC) | LBLC + 热点复制 | 解决 LBLC 单点过热 |
小结:WLC 作为默认算法是有道理的——它在最少连接的基础上加入了权重修正,既考虑了实时负载又考虑了机器性能差异。一般不需要改,除非有特殊需求。
SED 有个坑:如果 RS1 权重=1、RS2 权重=10,前 10 个请求全打到 RS2 上,RS1 啥也不干。这就是 NQ 算法存在的意义——它强制第一轮均匀分配。
3.3 内核 4.15+ 新增的两个算法
这两个算法比较新,但在特定场景非常实用:
- FO(Fail Over):可以手动标记某台 RS 为"过载"状态,调度器会跳过它。这个在做灰度发布时特别有用——先把一台 RS 标记过载,等它上面没连接了再下掉,平滑无感知。
- OVF(Overflow Connection):连接数超过权重值就不再调度。相当于给每台 RS 设了一个"最大承载量"。
四、NAT 模式实战
这一节完整记录了搭建 NAT 模式的全过程。建议动手做一遍,很多东西光看是看不懂的。
4.1 实验环境
用 4 台虚拟机模拟了整个环境:
网络规划:
- 公网段:
172.25.254.0/24(客户端和 VS 的外网侧) - 内网段:
192.168.0.0/24(VS 的内网侧和所有 RS)
各主机角色与 IP 配置:
| 主机 | 角色 | 网卡/接口 | IP 地址 | 网关 | 说明 |
|---|---|---|---|---|---|
| client | 测试客户端 | eth0 | 172.25.254.104 | — | 从公网发起请求 |
| VS | 调度器 | eth0(外网) | 172.25.254.100 | — | VIP,客户端访问这个地址 |
| eth1(内网) | 192.168.0.100 | — | DIP,跟 RS 通信 | ||
| RS1 | 真实服务器 | eth0 | 192.168.0.101 | 192.168.0.100 | 网关指向 DIP |
| RS2 | 真实服务器 | eth0 | 192.168.0.102 | 192.168.0.100 | 网关指向 DIP |
数据流向:
客户端 → VS(eth0/VIP) → VS 改目标IP → VS(eth1) → RS → 回包经 VS → 客户端💡 配置要点速记:
- VS 双网卡,一个对外挂 VIP,一个对内连 RS
- RS 网关必须指向 DIP——NAT 模式回包要经过 VS 做源地址转换,不然后端回包客户端不认识
- RS 不需要外网,纯内网就行
4.2 逐步配置
① 开启内核路由转发
echo"net.ipv4.ip_forward=1">/etc/sysctl.d/ip_forward.confsysctl--system💡 为什么要开这个?NAT 模式下 VS 要充当路由器——从一个网卡收到包,改完包头后从另一个网卡发出去。如果 ip_forward=0,Linux 收到非本机的包会直接丢弃。
② 安装 ipvsadm
yuminstallipvsadm-y③ 添加调度规则
# -A: 添加集群服务 -t: TCP协议 -s: 调度算法ipvsadm-A-t172.25.254.100:80-srr# -a: 添加RS -r: RS地址 -m: NAT模式ipvsadm-a-t172.25.254.100:80-r192.168.0.101:80-mipvsadm-a-t172.25.254.100:80-r192.168.0.102:80-m💡 NAT 模式的关键参数是
-m(masquerade,伪装)。DR 模式用-g(gateway),TUN 模式用-i(ipip)。容易搞混,记忆诀窍:masquerade=NAT 的伪装;gateway=DR 的网关;ipip=TUN 的隧道。
④ 查看规则
ipvsadm-Ln# IP Virtual Server version 1.2.1 (size=4096)# Prot LocalAddress:Port Scheduler Flags# -> RemoteAddress:Port Forward Weight ActiveConn InActConn# TCP 172.25.254.100:80 rr# -> 192.168.0.101:80 Masq 1 0 0# -> 192.168.0.102:80 Masq 1 0 0注意 Forward 列显示Masq,说明工作在 NAT 模式。
⑤ 测试
forNin{1..6};docurl172.25.254.100;done# RS2 server - 192.168.0.102# RS1 server - 192.168.0.101# RS2 server - 192.168.0.102# RS1 server - 192.168.0.101# RS2 server - 192.168.0.102# RS1 server - 192.168.0.101完美轮询 ✓
4.3 改为加权轮询
现实中后端服务器配置不太可能完全一样,加权就很重要:
# 修改调度算法为 WRRipvsadm-E-t172.25.254.100:80-swrr# RS1 权重 2,RS2 权重 1——RS1 会承担约 2/3 的流量ipvsadm-e-t172.25.254.100:80-r192.168.0.101:80-m-w2ipvsadm-e-t172.25.254.100:80-r192.168.0.102:80-m-w1测试结果:
RS1 RS1 RS2 RS1 RS1 RS2 ← RS1 明显分配更多4.4 规则持久化
这是容易被忽略的一步。ipvsadm 配置是存在内存里的,重启就没了!
# 保存当前规则ipvsadm-Sn>/etc/sysconfig/ipvsadm-config# 重载规则(模拟重启后恢复)ipvsadm-C# 先清空ipvsadm-R</etc/sysconfig/ipvsadm-config# 再从文件恢复# 设置开机自启(systemd 会读取上述配置文件)systemctlenable--nowipvsadm.service⚠️ 踩坑记录:第一次配好 LVS 后重启机器发现策略全丢了,又得重新打一遍。后来才知道 ipvsadm.service 的启动脚本会从
/etc/sysconfig/ipvsadm自动加载规则。
五、DR 模式实战
DR 模式是 LVS 的精华,也是配置最复杂的一种。核心难点不是 ipvsadm 命令,而是网络配置和 ARP 问题。
5.1 实验拓扑
DR 模式比 NAT 多了一层路由器,因为 RS 的网关不能指向调度器(DR 模式下回包不经过 VS,必须走路由器出去)。
网络规划:
- 公网段:
172.25.254.0/24(客户端和路由器外网侧) - 内网段:
192.168.0.0/24(路由器内网侧、VS、所有 RS)
各主机角色与 IP 配置:
| 主机 | 角色 | 网卡/接口 | IP 地址 | 网关 | 说明 |
|---|---|---|---|---|---|
| client | 测试客户端 | eth0 | 172.25.254.10 | 172.25.254.100 | 经过路由器访问内网 |
| router | 路由器 | eth0(外网) | 172.25.254.100 | — | NAT 模式,做 SNAT 转发 |
| eth1(内网) | 192.168.0.10 | — | 内网网关 | ||
| VS | 调度器 | eth0 | 192.168.0.200 | 192.168.0.10 | 调度器内网 IP |
| lo | 192.168.0.100/32 | — | VIP,/32 掩码只表示单个 IP | ||
| RS1 | 真实服务器 | eth0 | 192.168.0.101 | 192.168.0.10 | 网关指向路由器 |
| lo | 192.168.0.100/32 | — | VIP,ARP 抑制(对外装死) | ||
| RS2 | 真实服务器 | eth0 | 192.168.0.102 | 192.168.0.10 | 网关指向路由器 |
| lo | 192.168.0.100/32 | — | VIP,ARP 抑制(对外装死) |
数据流向:
请求:客户端 → 路由器(SNAT) → VS(改MAC) → RS 响应:RS → 直接回客户端(不经VS!)💡 关键区别:RS 的网关指向路由器
192.168.0.10,不是指向调度器。因为 DR 模式下响应直接回客户端,不需要经过 VS。
💡 关键点:VS 和所有 RS 都在 lo 接口上配了同一个 VIP(192.168.0.100/32),但 RS 必须通过 ARP 抑制"假装没有这个 IP"——只有调度器能响应 VIP 的 ARP 请求。
5.2 核心难题:ARP 抑制
这是 DR 模式里最容易踩的坑,也是面试最喜欢问的。
问题:RS 也有 VIP,当客户端发 ARP 广播问"谁有 192.168.0.100?“的时候,调度器和 RS1、RS2 都会回答"在这!”。如果客户端记录了 RS 的 MAC 地址,后续请求就绕过调度器直接打到 RS 上了——负载均衡当场失效。
解决方案:让 RS 在 VIP 上"装死"。
# 方法:修改内核 ARP 参数(推荐方案)echo1>/proc/sys/net/ipv4/conf/all/arp_ignoreecho1>/proc/sys/net/ipv4/conf/lo/arp_ignoreecho2>/proc/sys/net/ipv4/conf/lo/arp_announceecho2>/proc/sys/net/ipv4/conf/all/arp_announce这两个参数到底什么意思?用人话翻译一下:
arp_ignore=1:别人问"谁有这个 IP?"的时候,只有当这个 IP 确实配在收到请求的那张网卡上时,才回答。VIP 配在 lo 上,而 ARP 请求是从 eth0 进来的,所以 RS 不会回答——完美!arp_announce=2:向外通告自己的 IP 时,只通告跟自己直连的网络里的 IP。VIP 跟内网不在一个网段?那就不说——再次完美!
💡 另一种方案是用
arptables直接 DROP 掉 VIP 相关的 ARP 包,但改内核参数更优雅,而且这也是官方文档推荐的方案。
5.3 调度器配置
# VS 上 VIP 配在 lo 接口(/32 掩码——只表示这个 IP,不代表一个网段)# /etc/NetworkManager/system-connections/lo.nmconnection# address2=192.168.0.200/32# 添加 DR 模式规则(-g 是重点)ipvsadm-A-t192.168.0.100:80-swrr ipvsadm-a-t192.168.0.100:80-r192.168.0.101:80-gipvsadm-a-t192.168.0.100:80-r192.168.0.102:80-gipvsadm-Ln# TCP 192.168.0.100:80 wrr# -> 192.168.0.101:80 Route 1 0 0# -> 192.168.0.102:80 Route 1 0 0注意 Forward 列显示Route而不是 NAT 模式的Masq。
测试验证:
forNin{1..6};docurl192.168.0.100;done# RS2 - 192.168.0.102# RS1 - 192.168.0.101# 均匀分发 ✓5.4 NAT vs DR 实战心得
做完两个实验后的感受:
- NAT 模式适合学习和小规模场景——思路直观,配置简单。但请求和响应都走调度器,调度器压力大,不适合大流量。
- DR 模式是生产环境的标配——响应直接回客户端,调度器几乎不占带宽。但配置复杂,特别是 ARP 抑制那一步,不理解的很容易配错。
- 不管哪种模式,规则持久化一定别忘了做。血的教训!
六、防火墙标记(FWM)——多端口的救星
6.1 问题的本质
这个问题在实验中真实遇到过:RS 上同时跑 HTTP(80) 和 HTTPS(443),如果分别建两个 LVS 服务:
ipvsadm-A-t192.168.0.100:80-srr ipvsadm-A-t192.168.0.100:443-srr那么 80 和 443 是独立轮询的!可能出现:
- HTTP 请求 → 轮询到 RS1
- HTTPS 请求 → 也轮询到 RS1(因为 443 有自己的轮询计数器)
如果这是一个需要登录的网站,用户通过 HTTP 登录到 RS1 后,HTTPS 请求被调度到 RS2,会话直接丢失,登录状态没了。
6.2 解决方案
核心思路:把 80 和 443 的数据包打上同一个标记,LVS 基于这个标记而不是端口来做调度。
# Step 1:在 iptables mangle 表打标记# 意思是:凡是发给 VIP、TCP 协议、端口为 80 或 443 的包,打上标记 6666iptables-tmangle-APREROUTING-d192.168.0.100-ptcp\-mmultiport--dports80,443-jMARK --set-mark6666# Step 2:LVS 基于标记 6666(而不是端口)创建服务ipvsadm-A-f6666-srr ipvsadm-a-f6666-r192.168.0.101-gipvsadm-a-f6666-r192.168.0.102-g验证:
curlhttp://192.168.0.100;curl-khttps://192.168.0.100# RS2 server - 192.168.0.102# RS1 server - 192.168.0.101 ← 两次请求分发到不同 RS,说明是统一调度的 ✓小结:FWM 本质上是一种"归类"机制——不管你在应用层叫什么名字(HTTP、HTTPS),到了传输层就是同一种流量,就应该用同一套调度策略。这个思路在运维中很有普适性。
⚠️ 注意:FWM 是在 PREROUTING 链上工作的。这跟 LVS 的 hook 点(PREROUTING 和 INPUT 之间)完美配合。但也意味着如果你在 PREROUTING 上做了其他可能干扰的规则,要特别小心。
七、持久连接——让用户不掉线
7.1 问题场景
LVS 默认每来一个请求就重新调度一次(除了用 SH 算法)。但这在下面这些场景下会出问题:
- 用户登录后,session 存在 RS1 上,下一个请求被调度到 RS2 →登录状态丢失
- 用户填了半天的表单,提交时被调度到另一台 RS →表单数据没了
- 购物车加了商品,刷新页面后车空了 →用户体验灾难
SH 算法(源地址哈希)能部分解决,但太粗暴——同一个出口 IP 后面可能成百上千用户,全粘在一台 RS 上,负载严重不均衡。
7.2 LVS 的持久连接方案
LVS 的做法比 SH 聪明得多:在内存里建一张"持久连接模板表"。
- 客户端第一次来 → 正常调度(比如轮询到 RS2)
- LVS 记录一条模板:
IP=客户端IP → RS=RS2,有效期=超时时间 - 在超时时间内(默认360 秒),同一客户端的所有请求都走这条模板,不经过调度算法
- 超时后模板失效,下次请求重新调度
# -p 指定超时时间(秒)ipvsadm-E-f6666-srr-p3000# 查看持久连接状态ipvsadm-Ln# FWM 6666 rr persistent 3000 ← 看到 persistent 说明启用了# 实时监控连接表(非常有用!)watch-n1ipvsadm-Lnc# pro expire state source virtual destination# TCP 01:56 FIN_WAIT 172.25.254.99:42420 192.168.0.200:80 192.168.0.20:80# IP 00:57 ASSURED 172.25.254.99:0 0.0.26.10:0 192.168.0.20:0💡 注意连接表里有一条
IP协议、端口为 0 的条目,状态ASSURED——这就是持久连接模板。它的 expire 倒计时到 0 后,同源客户端才会被重新调度。
小结:持久连接跟 SH 算法的本质区别是:SH 是永久绑定(同一个 IP 永远去同一台 RS),持久连接是临时绑定(一段时间内去同一台 RS,过期后可以换)。持久连接+WLC 的组合是实际生产中最常见的配置——既能保证会话连续性,又能保持负载均衡。
八、LVS + Keepalived 高可用概述
8.1 问题来了
学完前面你会发现一个大问题:LVS 调度器自己是一个单点故障(SPOF)。
你费劲心思搭了 DR 模式、配了加权轮询、做了持久连接……结果调度器宕机了,整个集群全挂。这就是"高可用"要解决的问题。
8.2 Keepalived 怎么解决
Keepalived通过VRRP(Virtual Router Redundancy Protocol)实现多台调度器之间的主备切换:
- 两台(或多台)LVS 调度器组成一个 VRRP 组
- 主调度器持有 VIP,对外提供服务
- 主调度器定时发 VRRP 心跳包给备调度器
- 备调度器收不到心跳 → 判定主挂了 →自己接管 VIP
- 整个过程对客户端透明,切换时间通常在 1-3 秒
配合VRRP Script还可以做更智能的检测——不只是看调度器有没有宕机,而是检查整个链路是否健康(比如 RS 全挂了也可以触发切换)。
阿里云 SLB = LVS + Keepalived 的工程化实现。你在云控制台上点几下鼠标创建一个 SLB 实例,背后就是这套机制在运转。
九、ipvsadm 命令速查
这一节是常用的命令备忘录,按操作类型整理:
集群服务管理
# 添加ipvsadm-A-t172.25.254.100:80-srr# TCP,轮询ipvsadm-A-f6666-swrr# 基于防火墙标记# 修改ipvsadm-E-t172.25.254.100:80-swrr-p3000# 改算法+持久连接# 删除ipvsadm-D-t172.25.254.100:80# 清空所有规则(慎用!)ipvsadm-CRS 管理
# 添加 RS(-m: NAT / -g: DR / -i: TUN)ipvsadm-a-tVIP:PORT-rRIP:PORT-g-w2# 修改权重ipvsadm-e-tVIP:PORT-rRIP:PORT-g-w3# 删除 RSipvsadm-d-tVIP:PORT-rRIP:PORT查看 & 调试
ipvsadm-Ln# 查看规则(-n 不做 DNS 反解,快很多)ipvsadm-Ln--rate# 看速率:CPS/InPPS/OutPPS/InBPS/OutBPSipvsadm-Lnc# 看当前连接表(排查调度问题神器)ipvsadm-Z# 清空计数器ipvsadm-Sn# 保存规则(输出格式可直接重定向到配置文件)ipvsadm-R</etc/sysconfig/ipvsadm# 从文件重载关键文件
| 文件 | 作用 |
|---|---|
/proc/net/ip_vs | 当前 LVS 规则(十六进制格式) |
/proc/net/ip_vs_conn | 当前所有连接的状态表 |
/etc/sysconfig/ipvsadm-config | 规则持久化文件(ipvsadm.service 启动时读取) |
总结:学习心得
学完 LVS,最大的感受是:好的基础设施软件,都是把复杂的底层细节封装成简洁的接口。
LVS 的四个模式、十几种调度算法、持久连接、防火墙标记……看起来知识点很多,但核心就一条链路:
客户端 → VIP → [调度算法选择 RS] → [模式决定怎么转发] → RS → 响应回去把这条链路理清楚,每个环节该配什么参数就自然知道了。
几个最重要的小结:
- DR 模式是首选——生产环境 90% 都用它。掌握 ARP 抑制的原理才能在面试中讲清楚。
- WLC 算法默认就用它——加权最少连接是最通用的选择,没有特殊需求不用换。
- 持久连接
-p和 FWM 防火墻标记是两个实际生产中非常常用的特性,但入门教程经常忽略。 - Keepalived 补齐最后一块拼图——LVS 解决负载均衡,Keepalived 解决调度器自身的高可用。两者结合才是完整的生产方案。
- 七层和四层是配合关系不是竞争关系——LVS(四层,快)+ Nginx/HAProxy(七层,灵活)是经典的组合架构。
搞懂了 LVS,再去看云厂商的负载均衡产品,你会发现它们底层基本都是这套东西的封装。这也是一直强调"学好基础"的原因——基础扎实了,上层的东西都是透明的。