1. 单机扛不住流量了:为什么我最终选择了 LVS
先讲一个真实场景。去年我做了一个电商类的小项目,上线初期一台 4 核 8G 的云服务器跑 Nginx + PHP + MySQL,日活几千人完全没压力。结果到了某次促销活动,流量突然涨到平时的十几倍,CPU 直接 100%,数据库连接数被打满,页面响应时间从 200ms 飙升到 8 秒。我当时的第一反应是加配置,把机器升到 16 核 32G,但成本翻了几倍不说,没过多久流量再涨,又扛不住了。
这其实是很多团队从单体架构走向集群架构时的必经之路。单机时代,加配置是唯一解法;但一旦流量进入千万级、亿级,或者你有高可用需求,单机的天花板就卡在那里了。这时候你需要的不是更强的单机,而是一组机器组成集群,再有一个“流量调度的大脑”把请求分发给集群里的每一台机器,同时还要保证即使某一台挂了,整体服务也不中断。
这个“大脑”就是负载均衡器。当前主流的负载均衡方案有这几类:
- 软件四层负载均衡:LVS(Linux Virtual Server)、DPVS(基于 DPDK 的 LVS 增强版)
- 软件七层负载均衡:Nginx、HAProxy
- 云厂商自带的 SLB/CLB:本质上底层也是四层+七层组合
我最终选择 LVS,最大的原因是它工作在 Linux 内核态,直接在内核里做流量转发,不经过用户态拷贝,单机并发能力可以做得很高。在同样的硬件条件下,Nginx 作为七层负载均衡器,通常能支撑几万到十几万的并发连接,而 LVS 可以轻松做到几十万甚至百万级,而且延迟更低。它不解析 HTTP 内容,不关心 URL、Cookie、Header,只看 IP 和端口,所以吞吐量极其可观。
这篇文章我就把 LVS 这套东西从原理到实战完整梳理一遍,包括它的三层调度架构、三种工作模式、调度算法选型、与 Keepalived 配合做高可用,以及我在生产环境踩过的坑。适合刚接触集群架构的运维、后端开发,以及正在做架构选型的技术负责人。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. LVS 到底是怎么工作的:三层架构与数据流转全拆解
2.1 三个角色的分工
LVS 的整个体系里只有三种角色,非常清晰:
- Load Balancer(LB / Director):整个集群的入口,负责接收外部请求,然后按照预设的调度算法把请求转发给后端服务器。它就是那个“流量调度的大脑”。
- Real Server(RS):真正处理业务请求的服务器,可以是一台 Nginx、一个 Tomcat、一组 MySQL,或者任何你觉得需要被横向扩展的服务。RS 的数量可以从两台到几百台。
- Shared Storage(可选):如果后端业务涉及文件上传、静态资源,RS 之间需要共享一份数据,这时候要挂 NFS、GlusterFS 之类的共享存储。如果业务本身是无状态的,这层可以省略。
这三者的关系可以类比成餐厅:LB 是大堂经理,负责把所有顾客安排到不同的餐桌;RS 是各个服务员和厨师,真正接待顾客;共享存储则是后厨的公共冰箱,所有厨师都能从里面取食材。
2.2 数据包的一次完整旅程
以最简单的 DR 模式为例,我画一条请求的生命周期(画不出图,我用文字描述):
- 客户端发起 HTTP 请求,目标地址是 VIP(虚拟 IP,也就是 LVS 对外的入口 IP),假设是 192.168.1.100:80。
- 请求到达 LB 的网卡,LB 内核里的 IPVS 模块通过 netfilter 框架的钩子函数拦截到这个包。
- IPVS 根据配置好的调度算法(比如加权轮询),从 RS 列表里选出一台目标服务器,假设是 RS1,IP 是 192.168.1.11。
- LB 把请求数据帧的目标 MAC 地址改写成 RS1 的 MAC 地址,然后原样扔到交换机上(注意,DR 模式不改 IP,只改 MAC)。
- 数据帧到达 RS1 的网卡。因为 RS1 的 lo 接口上也绑定了 VIP,所以 RS1 内核认为自己确实应该接收这个目标 IP 为 192.168.1.100 的包。
- RS1 处理完业务,生成响应包,源 IP 是 VIP 192.168.1.100,目标 IP 是客户端的 IP,直接回给客户端。响应完全不经过 LB。
这个流程最精妙的地方在于:请求流量经过 LB,但响应流量不经过 LB。对很多高带宽业务来说,响应数据往往远大于请求数据,这种“请求走 LB、响应走直连”的模式极大降低了 LB 的压力。
2.3 工作在 Linux 内核里的 IPVS
LVS 的核心组件是 IPVS(IP Virtual Server),它是直接编译进 Linux 内核的模块。你可以把它理解成在内核网络栈里加了一个“流量改写器”,监听 netfilter 框架的几个关键钩子点(LOCAL_IN、FORWARD、LOCAL_OUT),当匹配到 VIP 的流量时,按照你配置的规则改写目标地址或 MAC,然后重新注入内核网络栈。
这种内核态处理方式带来的直接好处是:
- 没有用户态和内核态之间的数据拷贝,性能损耗极低
- 不依赖进程调度,不会有进程上下文切换的开销
- 对 TCP/UDP 都支持,不只是 HTTP
检查你的系统里有没有加载 IPVS 模块,可以执行这个命令:
bash复制lsmod | grep ip_vs
如果没输出,可以用 modprobe 手动加载:
bash复制modprobe ip_vs
modprobe ip_vs_wrr
modprobe ip_vs_rr
modprobe ip_vs_sh
建议你把这些模块加入开机自动加载列表,避免重启后 LVS 失效。
3. 三种工作模式怎么选:NAT、TUN、DR 的对比与取舍
3.1 NAT 模式:最安全但最容易成瓶颈
NAT(Network Address Translation)模式的工作原理是:LB 接收到客户端请求后,通过 DNAT 把目标地址从 VIP 改成 RS 的 IP,然后把包转发给 RS;RS 处理完请求后,把响应包回传给 LB,LB 再通过 SNAT 把源地址改成 VIP,最后发给客户端。
整个过程中,请求和响应都要经过 LB,所以 LB 的网络吞吐量就是整个集群的上限。我实测过,用普通千兆网卡的服务器做 LB,NAT 模式压到 800Mbps 左右就接近极限了,
