LVS 和 Nginx 都能做负载均衡,但它们并不是同一层面的东西。LVS 是 Linux 内核级别的四层负载均衡器,Nginx 是用户态的七层反向代理,选型的核心不是比较谁更强,而是弄清楚流量入口在哪一层、需要什么能力。本文从实现原理到架构落地,把两者的差异讲透,并给出组合使用的推荐方案。

一、实现层级与转发原理的根本差异
LVS(Linux Virtual Server)由章文嵩博士开发,早在 Linux 2.4 内核时代就已进入主干。它的转发逻辑直接实现在内核的 Netfilter 框架之上,报文到达网卡后在内核态就被处理掉,不需要拷贝到用户态,因此处理报文的开销极小。LVS 工作在传输层,只看 IP 和端口,不解析应用层内容,所以它能转发 TCP、UDP 上的任何业务,数据库连接、Redis 访问这类非 HTTP 流量它同样能扛。
Nginx 则是一个标准的反向代理服务器。请求到达后,内核把数据交给 Nginx 进程,Nginx 在用户态完整解析 HTTP 协议,识别 Host 头、URL、Header、Cookie,然后再向后端建立连接转发。这个过程中数据要在内核态和用户态之间来回拷贝,还涉及进程调度,单机性能天然比 LVS 低一个量级。但换来的好处是七层能力:按域名分流、路径重写、修改 Header、压缩、缓存、限流,这些 LVS 都做不到。
从转发模式看,LVS 有 NAT、DR、TUN、FULLNAT 几种。生产环境最常用的是 DR 模式:Director 只改写报文的目标 MAC 地址,请求直接从 Director 转给 RealServer,响应报文不经过 Director 而是直接回给客户端,所以响应流量不构成瓶颈。这一点与 Nginx 完全不同,Nginx 是代理模式,请求和响应都必须经过它本身,大文件下载、视频流这类响应流量大的场景会直接压垮 Nginx 的带宽。
二、调度算法、健康检查与会话保持能力对比
调度算法方面,LVS 内置了十种左右,最常用的几种各有侧重:rr 轮询简单均匀,wlc 加权最小连接适合后端机器配置不均的场景,sh 源地址哈希可以实现简单的会话粘性,lblc 则适合缓存服务器集群。Nginx 的算法相对少一些,开源版支持轮询、加权轮询、ip_hash、least_conn 和随机,一致性哈希需要商业版或者第三方模块。但 Nginx 的算法能感知的内容更多,配合 map 和 split_clients 甚至能按 URL 参数做灰度分流。
健康检查是两者差距明显的地方。原生 LVS(基于 ipvsadm)不带主动健康检查,后端服务挂了它照样往上面发流量,通常需要配合 Keepalived 来做:Keepalived 定期探测 RealServer,发现异常自动从 ipvs 规则中摘除节点,恢复后再加回来,同时 Keepalived 还提供 VRRP 能力实现 Director 的主备高可用。Nginx 开源版默认只有被动检查,靠 proxy_next_upstream 和 max_fails、fail_timeout 判断后端是否可用,主动探测需要 nginx_upstream_check_module 模块或者商业版的 active health check。
会话保持方面,ip_hash 和 LVS 的 sh 算法本质都是客户端 IP 哈希,缺点是客户端经过代理或运营商出口变化后哈希失效。更通用的方案是应用层做无状态化,配合 Redis 存 Session,让负载均衡层彻底解放出来。
三、性能表现与容量规划
性能上两者不在一个量级。LVS 在 DR 模式下,单核每秒可转发十万级以上的小包,一台普通物理机轻松达到百万级 PPS、几十万 QPS 的转发能力,因为内核态转发几乎不消耗 CPU 做协议解析。Nginx 在七层 HTTP 短连接场景下,单机通常在几万 QPS 量级(具体取决于报文大小、是否开启 SSL、CPU 配置),开启 HTTPS 后由于 TLS 握手的加解密开销,性能还会进一步下降。粗略地讲,同样的硬件,LVS 的四层转发能力是 Nginx 七层代理的十倍以上。
但容量规划不能只看 QPS。LVS 的瓶颈在连接跟踪表和网卡带宽,NAT 模式下还要注意源端口耗尽问题,建议生产环境优先用 DR 模式并调大 nf_conntrack_max。Nginx 的瓶颈在 CPU 和端口数,尤其是作为代理时每个后端连接都要占用一个本地端口, upstream 连接默认是短连接的话,高并发下端口耗尽报错很常见,务必开启 keepalive 长连接池。
下面是一份生产上常用的 Nginx upstream 配置,供参考:
upstream backend {
least_conn; # 最少连接调度
server 192.168.1.11:8080 weight=3 max_fails=3 fail_timeout=30s;
server 192.168.1.12:8080 weight=1 max_fails=3 fail_timeout=30s;
server 192.168.1.13:8080 backup; # 备用节点,全挂才启用
keepalive 64; # 到后端的长连接池,避免端口耗尽
}
server {
listen 80;
location / {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header X-Real-IP $remote_addr;
}
}
四、典型选型方案:LVS 加 Keepalived 挂 Nginx 集群
真实的大型互联网架构里,两者往往不是二选一,而是分层组合。最经典的架构是:最外层用 LVS 加 Keepalived 做四层流量入口,VIP 通过 VRRP 漂移保证 Director 高可用;LVS 下面挂一组 Nginx 集群做七层分发,Nginx 再按域名、路径把请求转给不同的业务后端。这样 LVS 扛住了海量连接的接入压力,Nginx 只需处理需要七层能力的流量,SSL 卸载、静态缓存、灰度分流都在这一层完成。当 Nginx 成为瓶颈时,直接加机器挂到 LVS 后面即可,扩容是线性的。
Keepalived 的核心配置如下:
vrrp_instance VI_1 {
state MASTER # 备机写 BACKUP
interface eth0
virtual_router_id 51
priority 100 # 备机低于主机,如 90
advert_int 1
virtual_ipaddress {
10.0.0.100 # 对外暴露的 VIP
}
}
virtual_server 10.0.0.100 80 {
delay_loop 6
lb_algo wlc # 加权最小连接
lb_kind DR # DR 模式,响应不回 Director
protocol TCP
real_server 10.0.0.11 80 {
weight 1
TCP_CHECK {
connect_timeout 3
retry 3
delay_before_retry 1
}
}
real_server 10.0.0.12 80 {
weight 1
TCP_CHECK {
connect_timeout 3
}
}
}
中小型系统则没必要上这套组合。日均流量不大、后端十几台以内的场景,直接用 Nginx 或者云厂商的 SLB 就够了,引入 LVS 反而增加了 DR 模式下 RealServer 需要 ARP 抑制、绑定 VIP 到回环接口这些运维复杂度。总结成一句话:需要极致四层吞吐和稳定接入层用 LVS,需要七层业务能力用 Nginx,两者都不够时分层组合,把每层放到它最擅长的位置上。