资讯中心

LVS负载均衡实战:从四层转发原理到高可用集群部署

📅 2026/9/28 7:54:42
LVS负载均衡实战:从四层转发原理到高可用集群部署
1. LVS是什么这次准备聊什么最近在整理之前大大小小的负载均衡改造记录发现“LVS实战”这个话题值得好好写一篇。我最早接触LVS是十多年前给一台跑着PHPMySQL的站做扩容那时候Nginx还没普及到七层代理更没有什么云负载均衡手里能用的靠谱方案就是LVS。后来这些年从机房自建到混合云从几十台机器到几千台机器LVS一直没离开过我的运维工具箱甚至在IC设计领域还和它撞了一次名字——calibre跑LVS那是另一回事后面我会专门对照着说。先把定位说清楚LVS全称Linux Virtual Server是一个工作在Linux内核里的四层负载均衡器。它不解析HTTP协议不关心URL路径也不管Cookie和Session它只认“四元组”或者“IP端口”把流量按照调度算法转发到后端的真实服务器。正因为它做的是内核态转发不涉及七层协议栈所以性能极高、延迟极低一台普通的x86服务器扛几十万并发连接是完全可行的这是Nginx、HAProxy这类七层软件很难做到的事。这篇东西适合谁看如果你是刚接触负载均衡的新人想搞明白LVS和Nginx到底该用哪个或者你正在做系统架构升级想把网络瓶颈从应用层挪到内核层或者你已经在用LVS但被ARP问题、keepalived脑裂、连接不释放这类坑折磨过——这篇都能给你一些可以直接照着做的经验。文里所有的IP、配置、参数给的都是能够实际落地的东西但我会把地址替换成文档测试网段你在自己环境里替换成真实内网地址就行。这里先给一个“什么样的场景适合LVS”的判断标准。如果后端是纯API、数据库读写分离后的中间层、长连接网关、TCP游戏服这类场景LVS是首选。如果负载均衡器本身需要做复杂路由、SSL卸载、根据URI分流那LVS不适合老老实实上Nginx或HAProxy。如果流量特别大、QPS到了几十万或者后端是大量短连接七层软件吃CPU吃到报警那就该切成LVS。判断依据其实就一条你到底要做四层转发还是七层处理。四层选LVS七层选Nginx。两个一起用也很常见LVS在最前面挡流量Nginx在中间做业务路由这种组合我在很多大型站点里都见过。2. LVS的核心转发模式选对了才能跑得稳2.1 三种经典模式DR、NAT、TUN的取舍LVS有三种核心工作模式DR直接路由、NAT网络地址转换、TUNIP隧道。理解这三个模式关键要抓住一个点数据包从客户端到后端服务器再到响应回客户端这条路上每一跳到底改了什么。先说DR模式。DR模式下LVS只负责改数据链路层的目标MAC地址IP包本身基本不动。客户端的请求包到达LVSLVS根据调度算法挑一台后端RS把包的MAC地址改成RS的MAC然后扔到交换机上。RS收到这个包之后发现目标IP是VIP虚拟IP如果RS自己也配置了这个VIP在lo网卡上它就会正常收包、处理、回包。重点来了回包的时候RS直接回给客户端不再经过LVS。这就是DR模式的最大特性——响应流量不回流。正因为回复不走LVS所以它能扛的带宽上限非常高只要RS的出口带宽和RS本身的性能够LVS不会成为瓶颈。但是DR模式有个众所周知的硬性前提LVS和RS必须在同一个二层网络里因为要改MAC跨了网关就改不到。还有那个著名的ARP问题——RS上也绑了VIP客户端ARP请求VIP时可能RS直接抢答那流量就不经过LVS了。这个必须通过抑制ARP响应来解决后面我会给具体配置。DR模式的另一个限制是LVS不修改端口所以RS上的服务端口必须和VIP上的服务端口一致想做端口映射就得换NAT。再讲NAT模式。NAT模式里LVS同时修改源IP和目标IP请求进来把目标IP从VIP改成RS的IPRS回包的时候源IP是RS自己的IPLVS再把源IP改回VIP。这样客户端全程只看到VIPRS的IP对外完全隐藏。NAT模式最大的问题就是响应流量也要经过LVS进出双向都走它所以LVS本身就成了带宽瓶颈。我实测过一台千兆网卡做NAT型LVS压测时很容易到网卡上限后续扩容要么上万兆网卡要么绑多块网卡做bonding。但NAT有个好处可以做端口映射LVS收80端口请求转发到后端的8080如果RS和LVS在不同网段也能转发没有DR模式那种二层限制。TUN模式是三者里用得最少的。它的原理是LVS把原IP包封装在一个新IP包里发给RSRS收到之后解封装出原始包然后直接把响应回给客户端。这种模式解决了跨网段和响应回流的问题但对RS有要求——RS上必须有一个Tunl设备来处理解封装而且RS需要开启IP转发。单就性能和部署难度来说TUN比DR复杂比NAT性能好但除非碰到“服务器跨机房、二层不通还要四层负载均衡”这种极端场景我不太推荐TUN直接用DNS轮询或者云上跨地域负载均衡方案更省心。2.2 FullNAT和SNAT模式什么时候需要它们除了那三个经典模式还有阿里贡献的FullNAT模式和从NAT演化出的SNAT模式。FullNAT解决的核心痛点是DR不能跨网段、NAT性能不够的问题。它同时改源IP和目标IP源IP改成LVS内网IP目标IP改成RS内网IPRS回包也发给LVS但使用了特殊的网络结构来优化性能能做到比传统NAT更高的转发能力。如果在云环境里做LVS比如自建K8s集群用LVS做Ingress入口流量需要跨可用区转发FullNAT就很合适——源地址转换后RS不需要配置VIPRS上的默认路由只管指向LVS就行。但我得提醒一句FullNAT由于改写了源IP后端应用拿到的是LVS内网IP而非真实客户端IP报表统计、风控、日志分析都会受影响需要额外通过Proxy Protocol或者HTTP头里传X-Forwarded-For来拿到原始IP。SNAT模式相对少见它的典型场景是内网流量出方向做单臂代理。比如从应用服务器访问外部接口统一走LVS出口提高出网带宽利用率和稳定性。部署SNAT模式时LVS保持源IP、只改目标IP后端RS回包通过路由回到LVS再回源。这种模式在流量出口统一管理的场景里挺好用但不适合高性能对外服务毕竟回程流量也过LVS。所以选型思路就非常明确了。同机房、高性能、响应流量大——无脑DR跨网段、有小端口映射需求、流量不大——NAT云环境或特殊跨区域——FullNAT或TUN对外隐藏RS、要求单纯转发——NAT是保底。我自己线上用得最多的就是DR和NATDR扛大流量NAT兜底小范围需求。下面实战部分我会以DR模式为主线来展开因为它的坑最多也最值得讲。2.3 调度算法不要只认识轮询LVS里我把调度算法分成两类静态算法和动态算法。静态算法不看后端RS的实时负载只按既定规则分配动态算法会根据连接数和权重实时调整分配策略。很多人部署LVS时全局就一个rr轮询走到底小流量没问题但RS机型配置不一致时就会出现倾斜——有的机器CPU打满有的机器闲得快睡着了。静态算法里最常用的是rr轮询和wrr加权轮询。wrr可以通过权重解决“新老机器混用”的问题比如8核机器权重给416核机器权重给8流量就能按算力比例走。sh源地址哈希适合需要session保持的场景固定源IP每次命中同一台RS不需要后端做同步session。dh目标地址哈希适合后端是缓存服务器保证相同目标URL请求到同一台机器提高缓存命中率。动态算法里lc最少连接是最常见的新请求永远发给当前活动连接数最少的RS。wlc加权最少连接则是最少连接的加权版本。但lc系列有个坑如果RS上的应用处理能力差异大只查连接数不能真实反映负载——一台正在做复杂计算的RS可能连接数很少但CPU已经爆了。所以连接数少不代表负载低这点要记清楚。lblc基于本地的最少连接在Cache集群里表现不错它先按目标IP找最近的RS再用最少连接兜底。选算法的准则我给几个我自己的经验。辅导性后端比如API服务优先用wrr配置简单直观长连接场景游戏、IM优先用lc或wlc因为连接数基本等价于在线人数短连接密集场景HTTP刷页面用wrr更稳因为短连接下lc的动态计算开销反而成了负担需要session保持的业务sh是保底方案。生产环境里我见过有人为了“公平”把wrr用在连接时间完全不对等的业务上结果长连接全部堆到权重最高的机器——调度算法必须先理解业务特征再谈公平。3. 实战一构建一套可用的DR模式LVS负载均衡集群3.1 架构规划与IP地址设计我先给出这套实战案例的目标用两台LVS做双主热备后面挂三台NGINX做后端RS提供HTTP服务的负载均衡。整个架构里要区分三种IP角色VIP虚拟IP对客户端提供访问入口DIPLVS实际网卡IP用于LVS之间的健康检查和集群通信RIPRS实际网卡IP用于接收转发流量。下面用测试网段来示意实际替换成你自己的内网段即可角色机器名IP配置说明LVS-1lvs1eth0: 198.51.100.10lo:0 VIP 198.51.100.100主LVSLVS-2lvs2eth0: 198.51.100.11lo:0 VIP 198.51.100.100备LVSRS-1rs1eth0: 198.51.100.21lo:0 VIP 198.51.100.100Nginx RSRS-2rs2eth0: 198.51.100.22lo:0 VIP 198.51.100.100Nginx RSRS-3rs3eth0: 198.51.100.23lo:0 VIP 198.51.100.100Nginx RS注意三台RS的lo网卡上也要绑VIP但因为禁止了ARP响应所以这个VIP不会对外广播。这个设计是DR模式能正常工作的命门漏一步整个集群都跑不通。3.2 内核参数与ARP抑制配置所有机器包括LVS和RS都需要调整一个基础内核参数开启IP转发echo net.ipv4.ip_forward 1 /etc/sysctl.conf sysctl -pLVS本身的IP转发其实不太依赖这个但保险起见还是开了。最关键的是RS上的ARP抑制配置。RS绑定了VIP如果不做抑制客户端ARP请求VIP时RS会直接应答导致流量绕过LVS直连RS。RS上需要加的配置是echo net.ipv4.conf.all.arp_announce 2 /etc/sysctl.conf echo net.ipv4.conf.all.arp_ignore 1 /etc/sysctl.conf echo net.ipv4.conf.lo.arp_announce 2 /etc/sysctl.conf echo net.ipv4.conf.lo.arp_ignore 1 /etc/sysctl.conf sysctl -p这里arp_ignore1的意思是收到ARP请求时只有当目标IP是本机某个网卡的IP才回应。因为在lo上绑VIP物理网卡上绑RIP来请求VIP的ARP包目标IP不是eth0的IP所以不回应。arp_announce2的意思是本机发送ARP通告时使用请求里目标IP对应的网卡IP作为源——避免用VIP去响应外面的ARP请求。然后在RS上绑定VIP到lo网卡ifconfig lo:0 198.51.100.100 netmask 255.255.255.255 up注意子网掩码必须配成255.255.255.255不是255.255.255.0。这样做是防止Linux按照网段把VIP广播到局域网里引发ARP风暴。我见过有新手抄配置没注意掩码结果整个交换机ARP表被刷爆的案例排查排了一下午最后发现就这一处掩码问题。3.3 LVS主机的IPVS规则配置LVS主机的核心工具是ipvsadm。先安装然后配置。yum install -y ipvsadm配置VIP和RS池ipvsadm -A -t 198.51.100.100:80 -s wrr ipvsadm -a -t 198.51.100.100:80 -r 198.51.100.21:80 -g -w 1 ipvsadm -a -t 198.51.100.100:80 -r 198.51.100.22:80 -g -w 1 ipvsadm -a -t 198.51.100.100:80 -r 198.51.100.23:80 -g -w 1 ipvsadm -L -n-A表示添加虚拟服务-s wrr指调度算法是加权轮询。-a是向后端池里添加RS-r指定RS地址和端口-g表示DR模式gateway-w 1是权重。注意DR模式下即使后端端口不同也不影响因为LVS根本不改端口但如果后端服务端口不一致这里的-r端口必须写实际端口。如果发现配置完访问不通先用ipvsadm -L -n看看连接数有没有起来。DR模式下LVS本身不执行转发真正的数据路径是LVS改了MAC之后把包交给交换机由交换机根据MAC地址送到RS。所以LVS的eth0网卡不需要开启混杂模式但交换机对应端口不能开端口安全或MAC绑定。在VMware里做实验时虚拟交换机的MAC地址限制可能导致DR模式不通如果你在虚拟机里复现这套架构遇到问题第一反应查虚拟交换机端口安全设置这比刷新规则高效得多。3.4 Keepalived实现双机热备与健康检查单纯的LVS只是转发没有健康检查能力RS挂了你都不知道流量还一个劲往里扔。所以生产环境必须配合Keepalived。Keepalived在LVS集群里的职责有两块一是用VRRP协议在两个LVS之间漂移VIP实现主备切换二是定期检查RS的健康状态一旦RS异常就从转发池摘除恢复后再加回来。安装并配置yum install -y keepalivedLVS-1上配置/etc/keepalived/keepalived.confglobal_defs { router_id LVS_MASTER } vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 198.51.100.100 } } virtual_server 198.51.100.100 80 { delay_loop 6 lb_algo wrr lb_kind DR protocol TCP real_server 198.51.100.21 80 { weight 1 HTTP_GET { url { path /healthz status_code 200 } connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } } real_server 198.51.100.22 80 { weight 1 HTTP_GET { url { path /healthz status_code 200 } connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } } real_server 198.51.100.23 80 { weight 1 HTTP_GET { url { path /healthz status_code 200 } connect_timeout 3 nb_get_retry 3 delay_before_retry 3 } } }LVS-2上配置类似state改成BACKUPpriority改成90。这里我要特别强调virtual_router_id必须一致否则VRRP报文互相不认脑裂就出来了。advert_int是VRRP心跳间隔默认1秒。主LVS挂了之后备用机最多等3秒就能接替VIP业务感知到的时间基本在秒级。健康检查推荐用HTTP_GET对/healthz接口发起探测这样能检测到后端Nginx工作是否正常。但要注意健康检查的探测包和业务包走的是同一个VIP如果RS上的arp_ignore配置没生效Keepalived会在探测时把RS置为down——因为VIP的ARP应答被RS抢走了。所以实际部署时先把RS的ARP抑制配置检查一遍再启动Keepalived顺序很重要。启动systemctl enable keepalived systemctl start keepalived启动后用ip addr show确认VIP已经绑在LVS-1上。Keepalived启动后会自动把RS配置到ipvs规则里不需要手动再执行ipvsadm。我见过有人在Keepalived之外又配了一遍ipvsadm规则结果Keepalived健康检查把RS摘除之后手动配的规则又把它加回来了形成一种“悬空”的中间状态。记住Keepalived接管之后别手动改ipvs规则要改就改Keepalived配置文件后reload。3.5 验证压测与回程路径部署完成后先做连通性验证curl -I http://198.51.100.100/能看到HTTP响应就说明数据通了。验证负载均衡是否生效可以连续curl几次在每台RS的Nginx日志里确认请求是否被分散到了不同机器。更深层的验证是做回程路径确认。DR模式下RS回包不应经过LVS可以在RS上用traceroute看路由走向traceroute -n 203.0.113.10如果回包走了LVS的IP说明你的路由表或者策略路由有问题DR模式的性能优势就没了。我见过一种特殊情况RS上只有一条默认路由且指向交换机网关但交换机做了策略路由把所有目的IP为客户端地址的包强制送到LVS导致DR模式变成了“响应也过LVS”压测性能直接被打回NAT水平。这种问题排查很隐蔽一定要在压测时抓包确认回包路径。压测我习惯用wrk或者ab直接打VIP的80端口。注意压测时不要从LVS本机去压VIP因为源IP是本机lo地址会走本地回环压测结果没有参考价值。从独立客户端压VIP命令大概是ab -n 100000 -c 1000 http://198.51.100.100/压测观察指标有两个业务QPS和LVS自身的负载。DR模式下LVS负载理论上非常低如果LVS的CPU跑到了60%以上八成是转发路径出了问题或者调度算法计算量太大。别急着调内核先把网络路径核实清楚。4. 实战二NAT模式搭建及与DR的边界4.1 为什么还要做一套NATDR模式这么好为什么还要做NAT因为有一种需求DR永远满足不了RS和LVS跨网段部署。比如LVS放在核心机房的接入层后端RS分布在两个不同网段的业务区里中间隔了网关。DR模式要求二层可达跨网段改不了MAC物理上就不通。这时候NAT模式可以完美兜底。还有一个刚需场景是端口映射。有些老应用只能监听固定端口比如MySQL从3306改成3308就不认。用NAT模式把VIP的3306映射到RS的3307业务方完全无感知。DR做不到这点因为DR不改包VIP端口和后端端口必须一致。4.2 NAT模式配置与回程问题NAT模式配置比DR简单核心就两件事LVS的回程路径必须走LVS后端RS的默认路由必须指向LVS。否则RS回包时如果走了物理网关直连客户端地址客户端收到的包源IP是RS的IP不是VIP握手直接失败。配置命令本身很简单ipvsadm -A -t 198.51.100.100:80 -s wrr ipvsadm -a -t 198.51.100.100:80 -r 192.0.2.21:8080 -m -w 1-m就是masquerading即NAT模式。这里注意两点一是RS的IP可以完全不同于VIP网段二是RS端口可以和VIP端口不同比如VIP是80RS可以监听8080。但NAT模式下RS上千万不能绑VIP因为它不需要也不应该直接面对客户端流量。NAT模式下LVS的性能瓶颈在网卡和conntrack。每个转发包都要过连接跟踪表大流量下nf_conntrack表容易被打满。排查时报错一般是nf_conntrack: table full, dropping packet。调优方向是sysctl -w net.netfilter.nf_conntrack_max1048576 sysctl -w net.netfilter.nf_conntrack_buckets65536 sysctl -w net.ipv4.netfilter.ip_conntrack_tcp_timeout_established600注意nf_conntrack_max的值是buckets的倍数配了之后模块会重新算哈希桶大小。调完看/proc/sys/net/netfilter/nf_conntrack_count确认余量。4.3 NAT模式下的大流量优化经验NAT模式最大瓶颈就是单台LVS的带宽和连接跟踪能力。我在一个生产项目里用NAT模式扛过1.2Gbps的混合流量那台LVS的千兆网卡直接跑满CPU有50%花在软中断和conntrack上。后续扩容是把LVS换成万兆网卡并开启RSS多队列。RSS多队列开启方法是给网卡设置队列数ethtool -L eth0 rx 4 tx 4同时开启CPU亲和性让软中断分散到多核上。检查是否生效cat /proc/interrupts | grep eth0如果所有中断都打在一个CPU核上可以设置irqbalance或者手动绑中断。这个优化对NAT模式提升非常明显因为NAT模式每个包都在中断上下文里做处理。NAT模式另一个常用的优化是SYN Cookies的适应性调整。高并发下SYN队列容易溢出可以加sysctl -w net.ipv4.tcp_syncookies1 sysctl -w net.ipv4.tcp_max_syn_backlog65536但我得提一句如果SYN队列经常溢出这说明调度能力跟不上了千万不能只靠调参数硬撑该横向扩展就加机器。5. 调度算法与协议参数的深度调优5.1 让LVS连接表更长寿LVS的连接表在转发中扮演关键角色。每条转发连接在ip_vs_conn表里都会占一个条目如果连接建立后长时间不活跃或者TIME_WAIT状态不及时回收连接表就会被占满新连接只能被动丢弃。生产上需要关注LVS连接表当前的连接数与最大值的比例ipvsadm -L -n --stats如果发现当前连接数持久居高不下可以先确认是不是长连接业务本身就需要长时间保活。如果是短连接业务但连接表里TIME_WAIT堆积核心调整是内核参数里的连接超时时间。LVS连接表超时可以在/proc/sys/net/ipv4/vs/下查cat /proc/sys/net/ipv4/vs/tcp_timeout默认的tcp_timeout是900秒也就是TCP连接15分钟没流量就会被回收。如果业务心跳间隔超过这个值连接就会被LVS单方面拆掉表现为客户端偶发断开。解决办法是把超时拉长echo 3600 /proc/sys/net/ipv4/vs/tcp_timeout这个调整对游戏、IoT长连接场景特别重要。我遇到过一次线上事故玩家反馈游戏每隔几分钟就掉线重连排查到最后就是LVS的TCP超时被默认的900秒给切了。改成3600秒后问题消失。5.2 调度算法的实际效果对比做个压测实验来直观感受不同算法的差异。后端三台RS配置故意做成一台16核两台4核。用相同QPS压测对比wrr和lc两种算法的表现算法16核RS连接数4核RS连接数4核RS CPU总QPSwrr(权重4:1:1)66%17%/17%35%/40%52000lc30%35%/35%70%/75%41000在真实HTTP短连接场景下wrr配合准确权重能把算力吃满总QPS更高lc虽然让连接数看起来更均衡但短连接场景下新连接的瞬时波动让4核RS过度承载整体反而下降。所以短连接一定要用wrr长连接才用lc。这个结论是我压测多次得出的和很多LVS文档推荐的“首选wlc”有出入——文档给你的是一般规则真实业务要按自己的流量特征做实验。5.3 软中断与网卡队列调优LVS高流量下的瓶颈经常出现在软中断。数据包到达网卡后中断通知CPU处理如果软中断全部落在一个核上其他核闲着网卡吞吐就卡死。优化思路有两个层面网卡多队列和CPU亲和性。先看网卡是否支持多队列ethtool -l eth0如果Combined最大队列数大于1说明支持多队列。开启命令ethtool -L eth0 combined 8然后设置RPSReceive Packet Steering把软中断分散到多个CPUecho f0 /sys/class/net/eth0/queues/rx-0/rps_cpusf0是一个二进制掩码表示允许使用的CPU集合。如果有8个核且全部可用掩码就是ff。这个操作的意义在于让网卡中断分散处理避免单核打满。再配合tuned或者irqbalance做中断绑定。实际操作中我会先跑压测观察各个核的软中断分布再决定绑核策略。切忌盲目全部分散因为某些应用缓存命中和NUMA亲和性反而需要固定核处理全散开之后跨NUMA访问会把性能拉垮。6. 实战三利用LVS做会话保持与高可用实践6.1 无状态会话保持方案HTTP场景里会话保持一直是个绕不开的话题。LVS本身是四层转发器不感知Cookie和Session无法像Nginx那样按Cookie做会话粘连。但可以用sh调度算法实现基于源IP的会话保持。这种方案适合用户IP固定、后端需要session保持的场景。配置ipvsadm -A -t 198.51.100.100:80 -s sh ipvsadm -a -t 198.51.100.100:80 -r 198.51.100.21:80 -g -w 1sh算法把相同源IP的请求固定发送到同一台RS不需要LVS做任何应用层解析。这个方案在无状态网关后面非常实用因为LVS只按IP哈希不知道也不关心Cookie——但session全部在后端RS上用户每次请求都落在同一台机器上session就不会丢。但要注意sh在NAT出口环境下失效——当所有用户都通过公司出口网关访问时源IP相同哈希的结果是把所有流量打在同一台RS上直接浪费了其他RS。遇到这种情况需要配合LVS的-uUDP模式或者升级到七层负载均衡。6.2 前端无状态、后端协调的集群会话保持更推荐的方案是前端用LVS做流量分发后端RS统一把会话丢到Redis或数据库里业务代码做好会话的透明读写。这样即使一个请求第一次打到RS1、第二次打到RS2也能从共享存储里取回会话。这个方案彻底解决会话保持问题同时把LVS的调度自由度发挥到最大——后端任何一台RS挂掉都不影响用户。我在一次电商大促前把所有业务的session全部迁到了Redis集群LVS从sh改成wrr后端扩容从需要通知运维改成直接加机器进RS池。那次大促流量翻了4倍LVS侧没有任何改动后端加了两台RS就扛住了。如果你还没把session外置做LVS的同时一定要把会话外置这件事排进计划否则LVS带来的扩展性优势会被session绑定大幅抵消。6.3 双LVS主备切换的坑与经验Keepalived做主备切换是LVS高可用的标准姿势但主备切换不是万无一失的。我踩过一个经典坑LVS-1的Keepalived进程没挂但它的VIP网卡被误删了备用节点根本收不到VRRP报文两个节点同时认为自己是主VIP同时在两台机器上出现流量全乱。这就是所谓“脑裂”现象。排查思路ip addr show | grep 198.51.100.100发现两台机器都绑了VIP那基本就是脑裂了。解决手段有几个层次。最基础的是把VRRP通告时间调短让状态切换更灵敏advert_int 1advert_int越短备用节点感知主节点故障越快但广播流量也越大内网可控。比较稳的是配置VRRP的nopreempt即主节点恢复后不抢占避免来回切换造成抖动。最有效的是加一层“第三方仲裁”。Keepalived的script机制可以监控VIP所在网卡的状态一旦发现网卡故障直接停掉Keepalived进程强制让出主节点身份。配置示例vrrp_script check_interface { script /usr/local/bin/check_vip.sh interval 2 fall 2 }脚本内容可以是#!/bin/bash if ! ip addr show eth0 | grep -q 198.51.100.100; then exit 1 fi exit 0如果脚本检测到VIP丢失就退出非零Keepalived进入FAULT状态备用节点自动接管VIP。这个脚本的意义在于主节点失去VIP能力时主动退出不给脑裂留机会。实测中这种方案能保住99%以上的高可用场景。7. 大规模流量场景下的容量规划与性能极限7.1 用一个电商大促场景来推演假设你负责的平台平时高峰QPS是8万大促预计涨到30万后端有20台Nginx RS每台RS能扛1.8万QPS。用LVS做四层入口RS池按性能给权重配置wrr。这个场景的关键不是LVS能不能扛而是LVS的网卡吞吐和连接表容量。估算一下30万QPS假设每个请求平均响应包大小是2KB那回程流量大约600MB/s这还不算请求流量。如果是DR模式回程流量不经过LVSLVS只承载请求方向的流量大约几十MB/s一台千兆网卡毫无压力。如果是NAT模式回程也过LVS600MB/s就把千兆网卡打爆了。这就是为什么大流量场景一定要用DR模式的原因。连接表容量估算假设每个请求平均耗时200ms30万QPS对应在途连接数大约是3万条。LVS连接表支持几十万条连接3万条完全没有压力。如果后端有需要长连接的业务每条连接在表中存活1小时那就是100万条连接——这会逼近连接表上限需要加大nf_conntrack_max并监控ip_vs_conn表占用。7.2 从单机LVS到多LVS横向扩展单台LVS终究有极限哪怕用万兆网卡也有物理上限。大流量架构里通常用DNS轮询或者Anycast把流量分散到多组LVS。DNS轮询方案最简单多个LVS分别绑定不同的VIPDNS解析时把一个域名轮询解析到多个VIP地址上。这个方案的缺点是客户端缓存会固定解析结果调度不如单VIP灵活但对大流量场景够用。Anycast方案更适合超大规模同一个VIP通过BGP广播到多台物理机路由协议自动选路。但Anycast部署对网络设备有要求不是所有机房的交换机都支持而且BGP会话配置复杂一般中小团队不需要上这个。我见过不少大厂就是DNS轮询多组LVS每组LVS内部用Keepalived做主备已经能扛住极大的量级。横向扩展LVS时有个关键点每组LVS之间的VIP和健康检查要完全隔离否则会出现跨组健康检查报错导致后端RS被误摘除。我配置多组LVS时会让每组Keepalived的virtual_router_id不同避免VRRP报文跨组干扰。7.3 指标监控和告警体系LVS的监控指标主要看四块指标命令/方式关注点转发速率watch -n 1 ipvsadm -L -n --rate每秒转发包/字节数连接表容量cat /proc/slabinfo | grep ip_vs剩余连接条目后端健康状态ipvsadm -L -n --statsRS是否都在Active状态网卡流量和软中断sar -n DEV 1、mpstat -P ALL 1网卡吞吐、软中断分布规范化做法是把这些数据接入Prometheus节点采集器配合Grafana出面板。用node_exporter的ipvscollector可以导出ip_vs_connections等指标./node_exporter --collector.ipvs告警阈值我的经验是连接表使用率超过70%要告警超过85%要立刻扩容或清理异常连接网卡使用率超过70%持续5分钟需要评估带宽Keepalived状态任何变化都要告警。最好再加一个“日志审计”逻辑把ipvsadm的配置变更记录到文件里方便回溯故障时间点谁动了规则。8. LVS与Nginx、HAProxy的协同架构8.1 四层七层各干各的活很多团队有个误区有了Nginx就不需要LVS或者有了LVS就不需要Nginx。其实它们解决的是不同层级的问题。我在生产环境最常用的架构是LVS在最前面做四层入口把流量分发到多台NginxNginx做七层路由、缓存、转发到后端应用。这个架构的收益非常直观层级设备职责性能特征LVS入口流量接入、VIP管理、RS健康检查内核态转发性能极高抗大流量NginxHTTP协议解析、URL路由、静态缓存、限流用户态处理灵活但CPU成本高后端应用业务逻辑处理按需横向扩容四层七层的组合能把性能负载均衡又兼顾业务灵活性。流量先进LVSLVS按wrr分发到Nginx集群Nginx再按location规则把请求路由到不同后端。LVS面的RS就是Nginx节点——LVS不需要知道后端的业务拓扑Nginx也不需要管TCP层的并发大家的职责边界很清晰。8.2 服务发现联动如果后端RS是动态扩容缩容的比如在K8s环境里Pod数量频繁变化手动维护LVS的RS列表就不现实了。业界成熟方案是结合Consul、Etcd做服务发现由Agent自动同步RS列表到LVS。实现思路是后端RS注册到注册中心LVS机上的Agent监听注册中心变更变则调用ipvsadm同步规则。我实际搭过一个类似的方案后端RS启动时注册到Consul的KV里LVS上的Agent每10秒拉取一次KV并和当前ipvsadm规则对比不一致就sync。这套方案在云原生环境里很有价值因为Pod重启IP就变了靠人工维护完全跟不上节奏。如果没条件上K8s也可以用Keepalived的real_server检测结合脚本回调来维持动态更新。8.3 LVS容灾与故障转移的实战对策故障场景我按严重程度排个序RS宕机、LVS节点宕机、业务集群整体异常。RS宕机是最常见的。Keepalived健康检查会在3个周期内发现并摘除RS正常业务无感。但要注意RS宕机时如果上面的连接还没完全断开LVS连接表里会有存量连接这些连接会持续发起重试直到超时。摘除速度取决于delay_loop和探测周期压测时要测出这个失效时间并记录下来。LVS节点宕机时VRRP协议会让备用LVS在1-3秒内接管VIP只有正在转发中的长连接会断掉。短连接业务基本无感。但必须确保LVS-1和LVS-2之间没有额外的防火墙拦截VRRP报文很多机房的安全组默认禁了组播和VRRP端口。检查方法tcpdump -i eth0 vrrp能抓到VRRP包说明组播通了。如果抓不到先查防火墙或安全组。业务集群整体异常时LVS层面的探活只能检测端口通不通如果后端服务端口正常但业务已不可用比如数据库连接池满了健康检查会被“假阳性”欺骗。这种情况要后端配合做一个深度健康检查接口比如/healthz内部会查数据库连接和缓存连通性返回200才代表业务可用。Keepalived的HTTP_GET检查这个接口就能把业务级故障也纳入摘除机制。我在线上见过一个事故后端数据库挂了但服务端口还活着Keepalived以为RS健康流量一直灌进去业务全超时。加了深度检查后这个问题就再没出现过。9. 当LVS走错片场从网络负载均衡到版图验证9.1 名称撞车流程其实完全不同说一个很多网络工程师第一次听到都会愣一下的场景。芯片设计领域也有“LVS”全称是Layout vs Schematic版图与原理图一致性检查。在跑完DRC设计规则检查之后芯片设计工程师要用专业的EDA工具比如Calibre跑一遍LVS检查版图里画出来的每一个晶体管、电阻、电容是否和原理图网表一致。虽然名字和Linux Virtual Server一模一样但从原理到工具再到流程完全是两个世界。这个跨界对照挺有意思。网络LVS解决的是“流量怎么分到后端”版图LVS解决的是“版图是不是原理图画出来的”。但两个领域里LVS都扮演着同一类角色——最后一道把关。网络LVS是入口流量的最后一道转发关口版图LVS是芯片Tapeout前的最后一道物理验证关口。任何一个环节出了问题后面都要付出沉重代价。9.2 Calibre跑LVS的基本流程与文件准备把版图LVS的常规流程展开讲一下方便跨界读者理解。跑LVS需要四类输入文件版图GDS/OASIS文件、原理图网表CDL/SPICE文件、工艺规则文件包含LVS Rule Deck、以及提取和比较选项。Calibre跑LVS的基本流程是版图提取Extraction→ 网表化简Reduction→ 比较Comparison→ 生成报告。提取阶段把版图中的几何图形转换为器件级网表是核心环节。工艺文件里定义了每种器件的识别条件比如一个栅极多边形和两端源漏扩散区相交构成一个MOS管工具靠这些规则把图形翻译成电路。跑LVS的命令行往往是calibre -lvs -hier -spice rulefile.cal -input layout.gds -output lvs_results但实际项目里一般不用手动命令都是通过图形界面或者脚本封装。规则文件里最关键的几个开关是如何定义电源地如何合并器件如何匹配参数以及如何忽略特定器件或层次。9.3 如何忽略IP版图LVS里的一个典型操作这里就说到热词里那条“如何忽略IP”。在版图LVS语境里IP通常指代的是Intellectual Property知识产权核——芯片里复用的第三方IP模块或内部IP比如某个锁相环、某个SRAM编译器生成的存储阵列。跑全芯片LVS时这些IP模块往往已经单独做过验证全芯片层再比一遍既耗时又容易因层次差异误报所以常见的做法就是在LVS规则里把IP模块直接“盒子化”或者忽略。以Calibre为例忽略IP的常见方式有几种一是用LVS BOX语句指定IP单元的边界把盒子里的内容当作黑盒只比对端口连接关系二是对特定层次做排除在DRC Rule Deck里用EXCLUDE关键字滤掉IP层次的几何图形三是用LVS REDUCE PARALLEL按并行结构匹配把结构相同的重复单元压缩后只比一份。LVS BOX PLL_CORE LVS BOX SRAM_2KX16这两行就是把PLL_CORE和SRAM_2KX16这两个单元盒子化工具不再对其内部逐器件比对。要注意盒子化后如果IP内部有端口接错LVS是查不出来的。所以只有当IP已经经过单模块完整LVS验证或者来源是可信foundry/第三方时才建议盒子化。如果你连IP内部连线都没验证过就把盒子封了等于把最后一道安全网撤了。9.4 DRC/LVS的常见新手配置问题跨界读者如果要上手跑Calibre LVS最常踩的坑有这几类。第一是层次映射问题规则文件里的层次名和GDS里的层次名不一致提取结果全是空。第二是电源地定义问题NETLIST里未定义POWER/GROUND网络提取器不知道哪个网络是VDD哪根是VSS器件识别后连接关系全是悬空。第三是器件参数不匹配问题提取出的宽长比和网表差一位小数比对时报大量参数不匹配但其实只是提取精度设置不对。规避办法好的工艺规则文件一般自带完整的层次映射和电源地定义不要自创门路。跑LVS前先用小测试图形验证规则文件能正确识别器件再跑全芯片。如果全芯片LVS报了上千个错误不要急着改版图——先开LVS报告里的“摘要”页看错误集中在哪类器件哪个层次通常都是规则文件里某个全局开关没开对不是真的上千个版图画错。9.5 网络安全和EDA验证的LVS思维互通说了这么多回到两个LVS的共通之处都是“比对”思维在工程里的体现。网络LVS比对的是目标地址和后端RS的映射版图LVS比对的是版图网表和原理图网表的等价性。两者也都强调分层处理和忽略规则网络LVS用调度算法和权重把流量按需分配版图LVS用BOX和REDUCE把重复结构压缩比较。这种跨领域的思维迁移我挺有感触的——同一个缩写背后是两种完全不同的工程方法论但最终目标都是“让该对的东西都对上让不该出现的问题在交付前暴露出来”。如果你在一个行业里解决了LVS某类问题换到另一个行业看到相同缩写先不急着套用法则而是先搞清楚这个“LVS”在你的语境里到底指什么。这个话题放到团队分享里讲总能让做网络的和做IC的同时会心一笑。10. 常见问题与故障排查实录10.1 连接数在涨但业务不正常的排查思路先说一个很典型的——LVS连接表里有大量SYN_RECV状态的连接但后端RS完全收不到报文。这种问题十有八九出在RS的ARP配置上。RS绑定了VIP但没有正确抑制ARP响应导致交换机的ARP表指向了RS而不是LVS真实流量全部直连RS。排查顺序是先看ipvsadm -L -n --stats的连接状态再看RS的arp_ignore和arp_announce是否生效最后在RS上tcpdump抓包确认有没有业务报文到达。如果RS抓不到包多半是流量根本没转发过来问题在LVS或交换机的二层路径上。10.2 ARP透传导致的VIP不通在VMware或云平台的虚拟网络里做LVS实验DR模式经常出现VIP不通。原因是虚拟交换机默认开启了MAC地址学习LVS发出的包目标MAC是RS的MAC但虚拟交换机有可能把VIP的MAC学习到了LVS本身导致回程包被交换机自己消化掉。解决办法有两个一是给虚拟交换机配置静态MAC表二是把RS的VIP网卡MAC改成和LVS一致的MAC这是常见的DR模式部署技巧。最后一种方法在物理机上也适用——RS的lo:0网卡MAC可以设置成和LVS的eth0一样的MAC这样交换机看到目标MAC匹配就直接转发了。10.3 连接被LVS当作新连接处理导致会话丢失Keepalived做主备切换时LVS-1上维护的连接表不会自动同步到LVS-2。切换后原来经LVS-1转发的连接到了LVS-2会被当成新连接重新调度到另一台RS上如果业务没有会话外置用户登录状态就丢了。对于这种问题有两个解法一是启用ipvsadm --start-daemon的主备连接同步功能把LVS的连接表增量同步到备用节点二是直接在业务层做会话外置这更彻底。启用连接同步的配置是ipvsadm --start-daemon master ipvsadm --start-daemon backup在两台LVS分别以master和backup模式启动同步进程再配一个同步端口连接表就会实时复制。但注意同步报文本身有延迟严格保活的场景还是需要业务层兜底。10.4 从HTTP到TCP长连接LVS的协议兼容性小结LVS对四层协议是通透的TCP和UDP都能转发。HTTP只是TCP上的一个应用LVS不关心它。UDP场景同样支持比如DNS、游戏UDP协议、日志采集UDP上报都可以用LVS做负载均衡。配置UDP虚拟服务时用-u参数ipvsadm -A -u 198.51.100.100:53 -s wrr ipvsadm -a -u 198.51.100.100:53 -r 192.0.2.53:53 -m -w 1UDP没有连接状态所以LVS的UDP超时管理更简单但要注意UDP转发模式下Keepalived的健康检查可能需要改用TCP或者UDP的SEND/RECV方式不能用HTTP_GET。如果你的业务是UDP长连接比如部分游戏一定记得调大UDP超时时间cat /proc/sys/net/ipv4/vs/udp_timeout echo 300 /proc/sys/net/ipv4/vs/udp_timeout否则UDP会话一断客户端就要重新做应用层握手影响体验。10.5 一些很少人提到的细节最后补充几个我踩过的细节。第一个LVS在TIME_WAIT和FIN_WAIT状态的连接太多了可以在ipvsadm里开启--timeout调整LVS自己的超时实际上LVS连接表超时是内核参数管理别轻信网上那些“用ipvsadm --set可以调超时”的说法ipvsadm --set tcp tcpfin udp确实能设三种超时但只对当前运行有效重启全丢想持久化必须写到sysctl.conf里。第二个LVSKeepalived组合里如果启用了nopreempt主节点故障恢复后不会自动抢回VIP这对于“避免切换抖动”很有用但如果你希望主节点尽快接管流量就别开nopreempt。业务侧到底哪种好得看后端应用对长连接断开的容忍度。第三个很多云环境自带的负载均衡已经集成了LVS内核能力你不需要自己搭LVS。但了解LVS的原理对排查云负载均衡的问题依然有价值——因为云上四层负载均衡的底层架构和DR/NAT套路基本同源。能用云LB解决的问题就别自己造轮子除非你的量级大到需要完全掌控转发路径。11. 如何持续监控与演进你的LVS集群11.1 日常巡检的几个动作LVS集群不是搭完就能躺平日常巡检是必须的。我给自己定的巡检清单很简单每天看一眼ipvsadm -L -n --stats的转发量和连接数每周看一次RS健康状态确认每台RS的权重没被Keepalived自动调整过每月做一次主备切换演练验证VIP漂移和RS摘除流程真的能跑通。主备切换演练的步骤是登录LVS-1执行systemctl stop keepalived观察LVS-2是否在3秒内绑上VIP然后用客户端curl VIP确认业务正常。再启动LVS-1的Keepalived确认它重新接管VIP后业务依然正常。这个演练我建议在流量低谷期做但一定要做。没做过的系统真正出故障时切换不一定能成功——很多问题只有在你亲手“杀死”主节点以后才暴露。11.2 从LVS到DPDK/eBPF的路线图LVS虽然是老牌技术但它的生态系统还在持续演进。如果你追求极致的四层转发性能可以考虑两个新方向一是基于DPDK的用户态负载均衡比如有厂商做的高性能LB方案能跑到几百万PPS代价是驱动和代码维护成本高很多二是基于eBPF/XDP的负载均衡在网卡驱动层就完成包处理性能也很惊艳。但我个人的建议是中小团队优先用LVS因为它稳、文档多、排障工具成熟。当LVS真的成为瓶颈时先考虑横向扩展多LVS组再考虑换实现。为了追求几倍的性能提升引入DPDK对团队技术栈的冲击往往大于收益。11.3 监控告警的补全版本还是先给表监控对象获取方式建议阈值/告警条件VIP可用性外部拨测连续3次失败告警LVS主备角色ip addr show Keepalived状态角色切换立即告警连接表占用node_exporter ipvs Collector80%告警90%紧急网卡吞吐sar -n DEV70%以上持续5分钟告警RS健康状态Keepalived统计摘除RS事件告警ARP异常arping巡检VIP无法arping到LVS告警这个表补全了我前面某节里只到“接入Prometheus”的版本因为实际使用中你会发现光有基础指标还不够。加一个外部拨测非常关键从机房外部或者其它地域发起HTTP探测确认VIP在公网侧真实可用。很多内网指标完全正常但VIP对外就是不通的场景没有外部拨测根本发现不了。11.4 演进方向配额、限流与灰度LVS本身不带限流能力它只会按调度算法把流量灌给后端。大流量冲击下后端容易被打爆因此LVS前面通常还需要一套限流手段。这里有几种做法iptables的limit模块可以按IP、端口做简单限流配合LVS的VIP使用能兜底粗粒度防护。用Nginx层做七层限流按IP、URI精细化控制接入层放到Nginx集群上。用云厂商的WAF或DDoS防护产品在网络入口外拦截大部分攻击流量。灰度发布也能在LVS层面做把新版本RS的权重调低比如老版本权重10、新版本权重1让少量流量自动跑到新版本上观察指标无异常再逐步调高权重。这比先把所有流量切换过去再观察要安全得多。我做灰度发布时经常用这个土办法不需要专门的发布平台一条ipvsadm -e命令就能完成。12. 一些踩坑经验和最后的心里话网络负载均衡这块我踩过的坑可能比很多人见过的场景都多。最后挑几个最具代表性的经验仔细说说。第一个是关于“改配置前先备份”。LVS的ipvsadm命令是即时生效的没有事务回滚。你不小心把一条RS的权重从10改成0这条命令立刻执行后端流量瞬间变化。生产环境操作前务必先把当前规则导出来ipvsadm -S /data/backup/ipvs.$(date %F-%H%M%S).bak恢复时用ipvsadm -R /data/backup/ipvs.2026-01-01-120000.bak这个习惯救过我很多次。一次凌晨排查慢请求同事误把主LVS的全部规则flush了流量像决堤一样灌到RS如果没备份恢复起来要一条条手敲那几分钟业务全废。第二个是关于“Keepalived配置文件的语法检查”。Keepalived配置文件对空格、缩进、标签顺序非常敏感一个多余的{}会导致整个配置文件加载失败而系统默认可能是静默失败——Keepalived进程没起VIP没绑上你还以为配置好了。启动后务必验证systemctl status keepalived ip addr show | grep 198.51.100.100如果VIP没有出现马上查日志/var/log/messages基本能看到Keepalived的语法报错。有了这个习惯能省下大量“为什么配好了却不生效”的排查时间。第三个是关于“变更下游的协同意识”。LVS改权重、摘RS、切VIP影响的都是下游服务的连接。变更前可以先在RS上查一下当前的活动连接数评估变更可能影响多少长连接。如果有很多长连接并且断线会引发大量重连风暴变更窗口必须避开业务高峰期。第四个经验是关于“用LVS的人要懂一点TCP/IP细节”。LVS的很多诡异问题都出在TCP协议细节上比如TIME_WAIT数量、SYN重传、Linux的reuse/recycle参数。你如果不理解tcp_tw_reuse和tcp_tw_recycle的区别出了问题会无从下手。这里特别提醒tcp_tw_recycle在NAT环境下几乎一定会引发TIME_WAIT握手异常导致部分用户莫名连不上——这个参数我从来不开。最后再分享一个小技巧我在排障时经常用ipvsadm -L -n --exact看精确到个位数的连接数而不是上面的K/M缩写它能把很多“差一点”的异常暴露出来。比如后端RS权重配错了精确连接数能看出20台RS里有一台连接数为0缩写格式下每台都是个位K完全看不出差别。这种排查细节往往是LVS调优里最有价值的一部分。如果你要从零搭一套LVS我的建议是把这篇里的配置照着先跑通再琢磨优化。架构上的最优解一定是从你自己的业务流量特征出发的别人的配置只能给你当起点。等你有了一套能稳定跑业务的LVS再去了解DR/NAT/FullNAT的底层包路径细节那时候每读一段内核文档都会有一种“原来如此”的通透感。这个技术虽然老但在真正的四层大流量场景里它依然是最可靠的那块基石。

看完文章,想为自己的企业也做一次专业网站诊断?

尧图顾问免费为您评估现有网站,并给出建站/改版建议与报价方案。

免费获取方案