news 2026/10/1 14:47:19

LVS负载均衡原理与Keepalived高可用集群实战:四层转发扛住亿级流量

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
LVS负载均衡原理与Keepalived高可用集群实战:四层转发扛住亿级流量

看到"LVS"这个词,我脑子里会先闪现两种完全不同的东西:一种是我们今天要聊的 Linux Virtual Server,另一种是芯片设计里的 Layout vs Schematic。如果你是因为跑芯片 DRC/LVS 摸进来的,那这里要给你提个醒——走错片场了。我们这边聊的是负载均衡,是那些日活千万、大促扛亿级 QPS 的系统里,站在 Nginx 前面那台看起来很不起眼、但流量全靠它分发的"老地基"。

在云原生架构满天飞的今天,很多人觉得 LVS 是上古产物,Service Mesh、网关、云负载均衡随便拉一个出来都比它"高级"。但真实情况是:只要你的系统流量到了一定规模,你会发现最底层那层四层转发、最扛压力、最不给你惹事的,还得是 LVS 这套内核态方案。这篇文章我会把 LVS 的原理剥开讲透,再带你把 Keepalived + LVS 主备集群从零搭一遍,最后聊聊我在线上踩过的那些坑,以及它在云原生体系里到底处于什么位置。适合所有正在设计高并发入口架构、或者被"怎么把入口层做得更稳"困扰的人。

1. 为什么说 LVS 是扛亿级流量最底层的"老地基"

1.1 一次大促压测暴露的真相

前两年我参与过一个电商平台的大促保障,入口架构长这样:客户端请求先到云负载均衡,再到 Nginx 集群,最后打到后端应用。当时所有人都盯着 Nginx 集群扩容,觉得"入口扛不住就加 Nginx 节点"。结果压测到一定量级,Nginx 的 connection 数飙得很快,CPU 冲到 80% 以上,但这还没到它的瓶颈——先崩的是云负载均衡的 SNAT 会话表和连接跟踪。

后来我们把最外层换成了自建的 LVS + Keepalived 集群,用两台普通的 x86 服务器,把原先分布在十台 Nginx 上的入口流量全部收进来。压测结果很有意思:LVS 节点 CPU 占用几乎没超过 10%,网卡吞吐跑满了,连接数几十万级别稳稳的。Nginx 集群压力倒是降下来了,因为四层转发不再经过它做无效的连接维持。

这就是 LVS 的核心价值:它在 Linux 内核态直接干活,不需要把数据包拷贝到用户态做解析,转发路径极其短。Nginx 是七层,每个请求都要做 HTTP 协议解析、头处理、连接管理,这些都要消耗 CPU。而 LVS 只管"这个包该发给谁",根本不关心里面装的是 HTTP 还是别的协议。

1.2 LVS 和 Nginx 的分工边界

很多刚接触架构的同学容易把这两个东西搞混,觉得"都是负载均衡,选一个不就完了"。但实际上它们的分工完全不同:

对比维度LVS(四层)Nginx(七层)
工作位置Linux 内核态用户态进程
处理内容IP + TCP/UDP 端口HTTP 协议、URI、Header、Cookie
转发能力极高,接近网卡线速受用户态进程和协议解析限制
连接处理转发连接,不维持应用状态持有连接池、upstream 状态
适用场景入口流量分发、数据库负载、TCP 服务HTTP 路由、安全过滤、静态资源、限流

生产环境里最经典的做法是 LVS 做最外层入口,Nginx 做中间层的七层路由,两层各干各的事。LVS 负责把流量按照某种策略分给后面的 Nginx 集群,Nginx 再根据 URI 把请求路由到具体的后端服务。这套组合我用了很多年,简单、稳定、出问题也好排查。云原生时代也一样,Kubernetes 里 Service 的 ClusterIP 在 ipvs 模式下,本质上就是拿 LVS 的内核模块在做四层会话分发。这一点后面我会单独展开。

2. 三种转发模式的血泪理解:NAT、DR、TUN 的数据流差异

LVS 有三大工作模式,很多人背概念背得滚瓜烂熟,但真正到了排障的时候就懵了。原因很简单——没把"数据包到底是怎么走的"想清楚。这一节我不用教科书式的那套话,直接跟你说人话。

2.1 VS/NAT 模式,为什么扛大流量必挂

NAT 模式下,客户端请求到了 LVS 节点(Director),Director 会把包的目的 IP 和端口改写为后端真实服务器(RS)的地址,然后转发出去。后端处理完,响应包要原路回到 Director,Director 再把源地址改回 VIP 回给客户端。

这个模式最大的问题是:请求和响应都必须穿过 Director,双向流量全压在它身上。比如后端返回一个 100KB 的图片,客户端发给 Director 的请求可能只有 1KB,但响应 100KB 还是得经过 Director 转一手。这意味着 Director 的带宽吞吐要能扛住所有后端服务的出站流量总和,这在实际业务里很难做到。

NAT 模式还有一个隐藏问题:由于 Director 要维护 TCP 连接的状态表(conntrack),在高并发下这个状态表会迅速膨胀。一旦超过 hash table 容量,新连接就会丢包或者被拒绝。我见过有人拿 NAT 模式扛过线上流量,结果就是高峰期 Director 频繁"内存溢出"。

NAT 模式唯一的优势是后端 RS 可以使用私网 IP,且不用做任何特殊配置(不需要配置 VIP 到回环口,也不需要 ARP 抑制),很省事。所以我个人的建议是:小规模场景、后端和 Director 跨网段、或者做实验环境,用 NAT 没问题;上生产扛大流量,换 DR。

2.2 VS/DR 模式:生产环境的绝对主力

DR 模式(Direct Routing)之所以能扛亿级流量,核心思路是让响应流量不经过 Director。具体数据流转是这样的:

  1. 客户端请求到达 Director,目标 IP 是 VIP。
  2. Director 通过调度算法选定一台 RS,然后把数据链路层的目标 MAC 地址改为 RS 的 MAC 地址,源 MAC 改成 Director 的 MAC,直接把这个帧在二层网络里发出去。
  3. RS 收到这个包,发现目标 IP 就是自己的 VIP(因为我们在每台 RS 的 lo:0 上都配置了 VIP),于是正常处理。
  4. RS 处理完,直接把响应包源地址设为 VIP,绕过 Director,走自己的网关回给客户端。

关键在于第 3、4 步:RS 必须在回环口 lo 上绑定 VIP,并且要抑制对这个 VIP 的 ARP 响应。否则整个局域网里的机器都会响应 VIP 的 ARP 请求,VIP 就乱了。

DR 模式里 Director 只处理入站方向的请求,所以它的压力极小。一台普通服务器跑 DR 模式,性能完全取决于网卡硬件和内核收包效率。我们之前用两台 2U 服务器做双主,单节点实测 4 万 QPS 的 HTTPS 新建连接毫无压力,长连接更是可以扛几十万。

DR 模式的前提约束是:Director 和 RS 必须处于同一个二层网络(同一个广播域),否则 Director 改完 MAC 帧发不出去。如果跨机房、跨 VLAN,就得用下面说的 TUN 模式。

2.3 VS/TUN 模式:异地多活的备选

TUN 模式是 Director 把原始 IP 包整个封装进一个新的 IP 包里,通过 IPIP 隧道发给 RS。RS 解封装后看到原始包,目标 IP 是 VIP,然后在本地处理,响应同样绕过 Director 直接回给客户端。

这个模式最大的好处是Director 和 RS 可以不在同一个网段,适合做异地机房的流量调度。但代价也不小:每个数据包多了 20 字节的 IPIP 隧道头,MTU 会受影响,大包容易被分片。而且 RS 上需要加载 ipip 内核模块并配置隧道接口,维护成本明显比 DR 高。

我实际见过用 TUN 模式的场景,多半是为了避开云厂商的访问控制策略,或者做跨地域的服务入口统一调度。常规单机房集群,我没太大必要用 TUN——DR 已经够用,维护还简单。

2.4 一张表把三种模式说清楚

模式转发对象响应路径RS 前提典型瓶颈适用场景
NATIP+端口改写往返都过 DirectorRS 任意网段Director 带宽和 conntrack小规模、跨网段
DR二层 MAC 改写响应直达客户端RS 与 Director 同二层,lo 绑 VIP二层网络范围单机房大流量入口
TUNIPIP 隧道封装响应直达客户端RS 支持隧道,需 ipip 模块MTU、隧道开销跨机房、异地多活

看到这里你应该理解了我标题里"基石"的意思:DR 模式把转发压力控制到了最低,让 Director 可以轻松成为亿级流量的分发节点。这也是为什么几乎所有大型互联网公司的四层入口,最底层都是 DR 模式 LVS。

3. 调度算法不是随便选的:从 RR 到 WLC,我的生产选型经验

3.1 静态算法和动态算法的区别

LVS 的调度算法分两大类:静态算法不关心 RS 当前负载,动态算法会根据连接数等实时指标做判断。

静态算法常用的有:

  • RR(轮询):一个接一个轮流分,最简单但没有差异化,适合后端能力完全一致的场景。
  • WRR(加权轮询):给不同 RS 配 weight,权重高的分得多。适合后端机器配置不一的场景。
  • SH(源地址哈希):根据客户端 IP 哈希去选 RS,同一个源 IP 固定打到同一台机器。
  • DH(目标地址哈希):根据目标地址哈希,一般用于缓存场景,把相同请求固定路由。

动态算法常用的有:

  • LC(最少连接):看当前活跃连接数,谁少发谁。
  • WLC(加权最少连接):LC 的基础上叠加权重,(当前连接数 + 1) / 权重最小的被选中。这是 LVS 的默认算法。
  • SED(最短期望延迟):(连接数 + 1) / 权重,对权重更敏感。
  • NQ(永不排队):SED 变种,优先给"当前没有任何连接"的 RS 派活。

3.2 为什么默认是 WLC,但你还得按场景换

WLC 是默认算法,说明它在大多数场景下表现确实不错,特别是 RS 处理能力均衡、请求处理时长相近的时候。但我在生产里遇到过两个 WLC 不太灵光的场景:

第一个是长连接场景。比如数据库连接池、Redis 代理这类保持大量长连接的服务,连接数这个指标根本反映不了真实负载——有的连接很闲,有的连接一直在跑大查询。这时候用 WLC 看活跃连接数意义不大,不如用 WRR 按机器规格定权重,或者干脆让后端自己做连接池负载。

第二个是后端能力不均衡的动态变化。比如某台 RS 因为 JVM GC 卡顿,实际处理能力下降,但 LVS 只看它连接数少,反而给它派更多的新请求——这就是所谓的"脑残式调度"。这时候我会调低它的 weight,或者用 SED/NQ 这种对权重更敏感的算法,让它快速被边缘化。

我自己的选型口诀是这样的:后端同配置、处理时间均衡,用 WRR;后端有差异、线程池模型,用 SED/NQ;需要会话保持,用 SH 而不是依赖 persistence_timeout;缓存场景,用 DH。

3.3 会话保持到底靠什么?

HTTP 场景有个经典问题:用户登录状态在 A 机器上,下一次请求被分到 B 机器,如果后端会话没有共享,用户就会掉线。很多人的第一反应是在 LVS 上配置会话保持。

LVS 确实有一个 persistence_timeout 参数,可以让来自同一个源 IP 的连接在固定时间内都分发到同一台 RS。这个参数在 keepalived 配置里很常见,默认值可以设成 600 或者按业务来。但它有一个先天缺陷:基于源 IP 做保持,如果客户端走了出口 NAT 或 IPv6 转换,大量用户共享同一个源 IP,就会造成严重的负载倾斜。

所以我的建议是:如果会话能放进 Cookie 或者 Redis 共享,就不要依赖 LVS 的 persistence;如果实在要依赖,用 SH 算法 + 合理 persistence_timeout,并且预估好 NAT 出口的份额,不要把保持时间设太长。80 到 120 秒足够覆盖大多数"跳转后马上回源"的场景,长保持时间的代价是流量分布极度不均。

4. Keepalived + LVS 主备集群搭建实录

4.1 拓扑与架构规划

我把这套配置在真实环境里跑了很多年,下面的步骤完全可以"抄作业"。架构就是一个标准的 LVS-DR 主备模式:

客户端 | | VIP: 192.168.10.100 | +--------+--------+ | | LVS主: 192.168.10.11 LVS备: 192.168.10.12 | | +--------+--------+ | +---------+---------+ | | | RS1: 192.168.10.21 RS2: 192.168.10.22 RS3: 192.168.10.23 (Nginx) (Nginx) (Nginx)

两台 LVS 节点部署 Keepalived 形成 VRRP 主备组,VIP 跑在主节点上。三台 RS 跑 Nginx,每台 RS 的 lo:0 都绑定 VIP。整个集群加起来五台机器,扛的入口 QPS 比前面十台 Nginx 直连还高,这就是 LVS 的杠杆效应。

4.2 主机初始化与配置

操作系统我用的是 CentOS 7.9 / Rocky Linux 9,都验证过。首先要装包:

yum install -y keepalived ipvsadm # RPM 系 # 或者 Debian/Ubuntu: # apt install -y keepalived ipvsadm

装完先把内核转发确认一下(NAT 模式必需,DR 模式其实用不到,但开了无害):

echo 'net.ipv4.ip_forward = 1' >> /etc/sysctl.conf sysctl -p

然后是加载 LVS 相关的内核模块。这一步很多人忽略,导致 keepalived 起来后ipvsadm -L -n一片空白:

modprobe ip_vs modprobe ip_vs_wrr modprobe ip_vs_wlc modprobe ip_vs_sh modprobe ip_vs_sed # 开机自动加载 echo -e 'ip_vs\nip_vs_wrr\nip_vs_wlc\nip_vs_sh\nip_vs_sed' > /etc/modules-load.d/ipvs.conf

4.3 keepalived.conf 逐段解读

主节点的配置文件/etc/keepalived/keepalived.conf完整版如下,我拆开讲:

global_defs { router_id LVS_MASTER } vrrp_instance VI_1 { state MASTER # 主节点;备节点写 BACKUP interface eth0 # VIP 绑定的网卡 virtual_router_id 51 # 同一个 VRRP 组必须一致 priority 100 # 主节点高于备节点 advert_int 1 # VRRP 心跳间隔 1 秒 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.10.100/24 dev eth0 } } virtual_server 192.168.10.100 80 { delay_loop 6 # 健康检查间隔 6 秒 lb_algo wrr # 调度算法,我这次用加权轮询 lb_kind DR # 工作模式 persistence_timeout 0 # 不依赖 LVS 做会话保持 protocol TCP real_server 192.168.10.21 80 { weight 1 # 权重按 RS 规格设 TCP_CHECK { connect_timeout 3 nb_get_retry 3 # 重试次数,默认是 nb_get_retry 但不同版本不同,下面说 delay_before_retry 3 connect_port 80 } } real_server 192.168.10.22 80 { weight 1 TCP_CHECK { connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } } real_server 192.168.10.23 80 { weight 2 # 新机器可以给更高权重 TCP_CHECK { connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } } }

几个容易踩的细节:

vrrp_instance 里的 state 和 priority 的关系。传统做法是主节点 state 写 MASTER、priority 写 100,备节点 state 写 BACKUP、priority 写 99。但实际 VRRP 选主只看 priority,两个节点都写 BACKUP、用优先级区分也没问题。我更推荐后一种写法,因为如果是"抢占式"主备,主节点恢复后 VIP 会强制切回,对于不那么需要强制回切的场景,反而会带来一次不必要的闪断。可以在主节点配置里加nopreempt,让主节点挂掉再恢复后不抢占。

auth_pass 只能在同一个组里用,不能跨组。我们之前两个业务共用一个 keepalived 进程,结果 auth_pass 设成了同一个,两台 LVS 的 VRRP 报文互相干扰,VIP 在两者之间反复横跳。排查了很久才发现是认证密码冲突导致的。

virtual_server 里的 lb_kind 大小写敏感。DR、NAT、TUN三个值必须严格大写,写成dr直接起不来。

4.4 后端 RS 的 ARP 抑制配置

DR 模式下 RS 这一侧是重头戏。每台 RS 都要把 VIP 绑定到回环口,同时抑制 ARP 响应。脚本如下:

VIP=192.168.10.100 # 绑定 VIP 到 lo:0 ifconfig lo:0 $VIP netmask 255.255.255.255 up # 抑制本机所有接口对 VIP 的 ARP 响应 echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce

这个配置的原理值得解释一下,网上的教程大多只给命令不给原因。

正常情况下,Linux 收到一个目标 IP 是本机 IP 的 ARP 请求,就会用自己的 MAC 地址回应。RS 的 lo:0 绑了 VIP,如果不做任何抑制,局域网里有人问"谁是 192.168.10.100",这台 RS 会抢答,这样客户端发往 VIP 的包就可能被 RS 直接截走,彻底绕过了 LVS,整个负载均衡就失效了。

arp_ignore = 1的意思是"只有目标 IP 精确匹配到本机某网卡配置的 IP 时,才响应 ARP 请求"。lo:0 配的是 255.255.255.255 的独立掩码,常规情况下不会对外响应;arp_announce = 2的意思是"对外响应的源地址,尽量使用目标网卡的 IP",避免出现 IP 匹配异常。

配置完成后建议验证一下:

ip addr show lo cat /proc/sys/net/ipv4/conf/all/arp_ignore cat /proc/sys/net/ipv4/conf/all/arp_announce

然后在客户端机器上观察 ARP 表:arp -a | grep 192.168.10.100,应该看到 VIP 对应的 MAC 是主 LVS 节点 eth0 的 MAC,而不是任何一台 RS 的。

4.5 验证命令和切换演练

LVS 集群搭完,验证不能只看"网页能打开"。我每次上线前固定会做四件事:

# 1. 确认虚拟服务和 RS 状态 ipvsadm -L -n # 输出里看到每条 real_server 的 ActiveConn/InActConn 在涨,说明流量真的在分发 # 2. 看各 RS 的连接分布 ipvsadm -L -n --stats # 3. 确认准备节点状态 systemctl status keepalived

第三步尤其重要,很多人搭完只盯着主节点。备节点 keepalived 起来后,它会持续监听 VRRP 报文,但不会配置任何 LVS 规则。只有主节点挂掉或者优先级变化,备节点才会接管 VIP 并把自己的 ipvsadm 规则加进去。所以验证备节点要主动做一次故障切换演练:

# 在主节点上停掉 keepalived systemctl stop keepalived # 观察备节点,等待 2~3 秒 ip addr show eth0 | grep 192.168.10.100 # 应该能看到 VIP 出现在备节点上 ipvsadm -L -n # 备节点的规则已经接管 # 从客户端再次访问 VIP,业务正常

演练完记得恢复:

systemctl start keepalived

需要提醒的是,如果配置了 nopreempt,主节点恢复后 VIP 不会自动切回,可能长时间停留在备节点上。这本身不是故障,但要有感知,别在第二天的监控里看到"咦,VIP 怎么在备机上"就慌。

5. 故障转移里那些看不见的细节:ARP、裂脑与连接跟踪

5.1 VIP 漂移时到底发生了什么

Keepalived 的 VRRP 协议本质上就是主备两台机器在同一个虚拟路由器 ID 下互发心跳报文。备节点连续几个advert_int周期没收到主节点的心跳,就判定主节点故障,开始接管 VIP。

接管过程不是简单地把 IP 配置到网卡上,关键动作是发送免费 ARP(Gratuitous ARP)。这个免费 ARP 的作用是告诉整个二层网络:"192.168.10.100 这个 IP 的 MAC 地址变了,你们赶紧把 ARP 缓存更新掉。" 交换机、路由器、客户端收到这个通告后,新的流量才会被引到新主节点上。

这里就有一个实战中很常见的坑:免费 ARP 只发一次,但下游设备的 ARP 缓存老化时间可能远超这个周期。如果交换机或者客户端没及时收下这个通告,流量就会继续往已经挂掉的老主节点上送,表现就是"切换了但业务还是在断"。解决方法是把 keepalived 配置里vrrp_notify脚本接到切主事件上,脚本里强制发几轮免费 ARP:

#!/bin/bash # /etc/keepalived/master.sh VIP=192.168.10.100 INTERFACE=eth0 for i in $(seq 1 5); do arping -I $INTERFACE -c 1 -U $VIP sleep 0.2 done

然后在这个脚本被调用的时机上做配置,一般用 notify 或者 smtp_alert 相关的钩子。不同 keepalived 版本的钩子名有差异,要对着自己版本查。

5.2 裂脑的成因与防护

裂脑(Split Brain)是主备高可用里最怕的事:主备两台机器都认为"我才是主",于是都绑定了 VIP。结果客户端 ARP 表在两套 MAC 之间反复横跳,流量被打到两台机器上,会话乱七八糟,业务表现就是"时好时坏,异常连接满天飞"。

裂脑的常见成因是心跳链路断了但业务网络还通,比如两台机器之间的 VRRP 报文被防火墙丢弃、交换机端口做了隔离、或者网卡链路抖动。我在线上遇到过最隐蔽的一次,是服务器上跑了一个安全软件,把 VRRP 用的组播报文当异常流量拦了,导致备节点误判主节点故障,直接抢占 VIP。

防护手段没有银弹,只能多管齐下:

  • 优先用单播模式替代组播,keepalived 配置里指定对方 IP,减少组播报文被交换机丢弃的概率。
  • 在 VIP 绑定网卡上用 iptables 限制,只放行同一个 VRRP 组的来源。
  • 写一个裂脑检测脚本,每几秒看一次"本机是否持有 VIP + 对方 keepalived 是否存活",两边都对就报警,必要时强制关闭本机 keepalived。

5.3 conntrack 在转发链路中的作用

这个话题我希望每个用 LVS 的人都能重视。DR 模式下,主节点为每个经过的 TCP 连接建立对应的 ip_vs 会话状态,这个状态存的是"四元组 → 转给哪台 RS"。故障切换后,新主节点的连接跟踪表是空的,所有老连接在新主节点看来都是"陌生连接"。

结果就是:切换瞬间,已有的 TCP 长连接会被打断。TCP 客户端会感知到 RST 或者连接超时,然后重连。对 HTTP 短连接业务来说,重连开销可接受;但如果是数据库代理、消息队列这类长连接业务,一次切换可能导致成千上万个连接同时重建,后端会瞬间被打爆。

这个问题的缓解措施有几种:

  • 用 conntrackd 做连接跟踪表同步,在主备之间实时同步状态,切换后新主节点能"继承"老连接,代价是配置复杂、同步本身也消耗资源。
  • 接受重连,给客户端配置合理的重试策略,然后靠 RS 的承载能力撑过切换瞬间。大多数互联网业务够用。
  • 在架构上把长连接收敛到更上层,避免直接挂在 LVS 后面。

我个人的判断是:如果业务对"切换瞬间断连接"完全不能接受,应该优先考虑在 RS 侧做重连保护,或者用云厂商提供的会话保持能力,而不是在 LVS 层硬扛 conntrack 同步的复杂度。

6. 生产环境踩坑清单:每一条都是真金白银换来的

6.1 keepalived 版本差异带来的配置"假成功"

keepalived 的配置语法在不同大版本之间有变化,尤其是健康检查相关的参数。我踩过一个很典型的坑:在 1.3 版本下用nb_get_retry和delay_before_retry没问题,但升到 2.x 后,部分写法被标记为 deprecated,甚至有些字段解析直接报错。报错还好,最怕的是配置解析静默失败,keepalived 起来了,虚拟服务也配了,但健康检查根本没生效,RS 挂了一台它还往里面转发。

所以每次升级 keepalived,我的固定动作是跑一遍keepalived -t -f /etc/keepalived/keepalived.conf做配置语法校验,然后看日志/var/log/messages里有没有 WARNING 级别的解析提示。别嫌麻烦,这条能救大命。

6.2 健康检查误判导致的雪崩

健康检查的connect_timeout设得太短,是我见过最危险的操作。比如后端 RS 处理本身要 200ms,你设了 100ms 的 connect_timeout,LVS 会判定这台机器不健康,然后把它移出调度列表。大量请求瞬间转移到其他 RS,其他 RS 压力升高、响应变慢,又被更严格的健康检查误判下线——雪崩就来了。

正确做法是健康检查超时时间要大于后端 P99 响应时间,同时配合多次重试判活。宁可让一台慢机器多活一会儿,也别把它过早摘掉导致整个集群连环崩。RS 的判断逻辑我建议"连续 2 次成功才算恢复,连续 2 次失败才摘除",避免单次抖动引起频繁上下线。这也是为什么我在配置里习惯写上delay_before_retry和重试次数。

6.3 权重不合理引发的流量倾斜

LVS 的权重调整是动态生效的,但很多人调整得太激进。我曾经为了给一台新机器引流,把新机器 weight 从 1 调到 5,然后在监控上看到它连接数瞬间冲破阈值。原因很简单:WLC 算法里权重是个"加速器",权重差距过大时,低权重的机器几乎被忽略,新连接全往高权重的机器灌。

正确的做法是分阶段调整权重,比如从 1 → 2 → 3,每阶段观察至少一个业务周期。尤其是在流量高峰期,权重突变比机器宕机还可怕。

6.4 后端 RS 的 sysctl 模板

长期使用 LVS 之后我整理了一套 RS 侧的 sysctl 基线,专门给挂在 LVS 后面的机器用:

# 提高文件句柄和连接队列 fs.file-max = 1000000 net.core.somaxconn = 65535 net.ipv4.tcp_max_syn_backlog = 65535 # 快速回收 TIME_WAIT 连接 net.ipv4.tcp_tw_reuse = 1 net.ipv4.ip_local_port_range = 1024 65535 # 加大 backlog,避免瞬时高并发丢连接 net.core.netdev_max_backlog = 65536

这里特别说一下tcp_tw_reuse,它是跟 LVS 联动的一个关键参数。LVS 转发请求到 RS 后,源 IP 是 VIP 或 Director 的地址,RS 回包时会产生大量 TIME_WAIT 连接。如果本地端口范围太小、TIME_WAIT 回收太慢,RS 会陷入"端口耗尽"的假死状态,表现是大量连接建立失败但 CPU 内存都正常。调大本地端口范围 + 开启 reuse,是 RS 挂在高流量 LVS 后面最基础的自保手段。

7. 云原生时代,LVS 的位置在哪里?

7.1 kube-proxy 的 ipvs 模式就是在复用 LVS 的底子

聊到云原生,很多人会误以为 LVS 只属于传统机房。但你只要拆开 Kubernetes 的底层就会发现,kube-proxy 支持 iptables 和 ipvs 两种模式,而 ipvs 模式用的就是 LVS 的内核能力。

在 ipvs 模式下,kube-proxy 把 Service 的 ClusterIP 建成一个虚拟服务,Pod 的 Endpoint 作为 real server,由内核态的 ipvs 直接做四层分派。相比于老式的 iptables 模式,ipvs 的规则更少、转发更快、支持更丰富的调度算法。一个几千个 Service 的集群,iptables 规则表能达到几万条,CPU 消耗明显;换成 ipvs 后规则量级大幅下降,新建连接性能也更好。

所以你可以这样理解:你在经典机房用 LVS 的经验,到了 K8s 集群里依然有效,只是从"手动配 keepalived"变成了"声明式 API 自动管理"。

7.2 裸金属 K8s 里怎么借 LVS 的能力

如果没有云厂商的负载均衡,裸金属 K8s 集群想暴露一个四层端口,常见的方案是 MetalLB。MetalLB 在 L2 模式下会选出一个节点承载 Service 的对外 VIP,本质上也是 ARP 抢占的思路。如果集群规模大、节点多,MetalLB 的性能瓶颈会暴露,这时候一部分团队会选择在集群前面放一个独立 LVS 集群,把集群节点当作 real server 挂进去。

我自己做过的一个典型架构是:三层入口,LVS(四层)→ Ingress Controller Nginx(七层)→ 业务 Pod。这套架构迁移到 K8s 几乎无缝,LVS 层完全不需要跟着集群折腾,Ingress Controller 扩容只在 LVS 后面加 real server 就行。这也是很多人忽略的一点:云原生并不是要把经典方案全都推翻,而是让 LVS 继续在最底层发光,上层换成更灵活的编排。

7.3 从 LVS 到四层网关的演进思路

LVS 之后,业界其实一直在演进四层网关技术,比如基于 DPDK 的用户态转发、基于 eBPF/XDP 的内核旁路、以及各种云厂商自研的四层 LB。它们解决的问题和 LVS 一样,只是换了一种更"吃硬件红利"的实现方式。

但 LVS 并没有过时,反而因为"简单、稳定、内核自带"这三个特点,依然是最值得优先考虑的四层入口方案。eBPF 和 DPDK 虽好,但对团队的技术储备和运维能力要求高了不少,一个 bug 可能影响整个集群转发面。对于大多数业务来说,用 Keepalived + LVS 搭出来的入口,十年如一日地稳定,这本身就是最大的价值。

我个人的建议是:如果你的流量还没有大到需要专项优化四层转发的程度,就老老实实用 LVS,把省下来的精力花在业务和后端服务治理上。等哪一天你发现 LVS 节点网卡打满了、单机吞吐成为瓶颈,再去研究 DPDK 和 XDP 也不迟——而且那时候你会更理解它们解决的是什么问题。

回到开头那个话题:为什么总说 LVS 是亿级流量的基石?原因其实很朴素——它在最靠近硬件的内核层做最纯粹的分发,把复杂留给了上层的 Nginx 和业务。我每次排障到入口层,最后发现最稳的还是那两台不起眼的 LVS 节点。这套方案我会一直用下去,也希望这篇拆解能让你在搭建自己的入口架构时少走点弯路。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/1 14:47:09

电阻电路等效变换全解析:从串并联到受控源与电源等效

作为一个正在啃电路基础的人,我最怕看到的就是那种看起来“理直气壮”的化简:明明是一个电阻网络,你却不知道从哪里下刀。串联、并联一眼能看出来还好,可一旦碰到T型、Π型、桥式结构,再夹杂个受控源,整个电…

作者头像 李华
网站建设 2026/10/1 14:46:37

Arclight混合服务端搭建教程:Forge Mod与Bukkit插件共存指南

在Minecraft服务器的圈子里,有一个长期折磨人的难题:装了Forge就跑不了插件,装了Spigot就装不了大型Mod。尤其是想开一个“既有科技Mod、又有生存辅助插件”的服务器时,基本只能在二选一里煎熬。Arclight这个混合服务端&#xff0…

作者头像 李华
网站建设 2026/10/1 14:46:33

IPD产品开发流程角色职责详解:从IPMT到PDT的落地指南

简介:面向IPD流程实践者与产品研发管理人员的角色职责说明文档,系统梳理集成产品开发全流程中核心角色的定义与分工,适合刚导入IPD的企业、产品经理及研发、财务、采购、市场等跨部门成员快速统一认知、明确岗位边界。文档围绕IPMT、PDT经理以…

作者头像 李华
网站建设 2026/10/1 14:45:49

PLC数据上云实战:工业网关+MQTT+Node.js搭建Web SCADA

工业现场的数据上云,很多人卡在第一步:PLC 里的数据怎么稳定、低成本地送到 Web 端。传统做法是买一套组态软件加授权,成本高、扩展性差,想接个自定义看板或者推给第三方系统,处处受限。这两年我陆续做了几个从 PLC 采…

作者头像 李华
网站建设 2026/10/1 14:45:15

Wireshark抓包实战:温湿度变送器SNMP与Modbus TCP故障诊断

前几天在客户现场处理一个很典型的故障:动环监控大屏上一片飘红,三号机柜的温湿度数据停在“通信异常”已经超过两个小时。现场三方各执一词,设备厂家说变送器指示灯正常、本地液晶屏还在刷新,网络工程师说交换机没有任何告警&…

作者头像 李华
网站建设 2026/10/1 14:44:51

剪贴板增强工具设计解析:历史记录、格式清洗与效率提升

1. 项目概述:一个看起来不起眼的 paperclip先说结论:这个项目叫 paperclip,但做的不是回形针,而是一套把“剪贴板”这个日常到容易被忽略的系统能力,重新做了一层封装和增强的工具。用我们这行的话说,它解决…

作者头像 李华