LVS负载均衡是什么?工作模式、调度算法与部署思路详解

一提到负载均衡,很多人的第一反应是 Nginx 或 HAProxy,但真正在超大流量入口扛住压力的,往往是 LVS。LVS(Linux Virtual Server)是 Linux 内核自带的一套四层负载均衡方案,工作在传输层,性能接近硬件负载均衡设备,却能跑在普通服务器上。它在阿里、腾讯、字节这些大厂的核心入口层被广泛使用,也是理解"四层负载均衡"绕不开的一课。

这篇文章把 LVS 讲透:它到底是什么、DR、NAT、TUN 三种工作模式的原理和区别,rr、wrr、lc、wlc、sh 等调度算法怎么选,ipvsadm 的基础命令怎么用,怎么和 Keepalived 结合做高可用,以及它适合和不适合的场景。文章会给出真实可执行的配置,并在涉及网络和内核参数改动时标注风险与回滚方式。Linux 部分按 RHEL/CentOS/Rocky 与 Debian/Ubuntu 两套发行版给出命令。

LVS 是什么:内核态的四层负载均衡

传统负载均衡按工作层次分四层和七层。四层看 IP 和端口,按连接转发;七层解析应用协议,按内容转发。LVS 属于四层,它的核心是 Linux 内核里的 IPVS(IP Virtual Server)模块,以及用户态的管理工具 ipvsadm。请求到达调度器后,IPVS 在内核里直接改写数据包的转发目标,不经过用户态处理,所以转发效率极高。

LVS 的角色划分很清晰:调度器叫 Director(也叫 Load Balancer,简称 LB),它对外提供一个虚拟 IP(VIP),接收所有请求;真实处理业务的是 Real Server(简称 RS),也就是后端的应用服务器。客户端只知道 VIP,不知道背后有多少台 RS。

LVS 的性能优势来自它的工作位置——内核态。Nginx 和 HAProxy 都以用户态进程处理请求,虽然性能也很高,但在极端并发下会受进程调度和内存拷贝影响。LVS 在内核里做包转发,连接建立后数据流几乎不受调度器影响,所以能扛住百万级并发连接。代价是它只能做四层,无法根据 URL 或 Cookie 做精细路由,也不理解 HTTP 语义。

三种工作模式:DR、NAT、TUN

LVS 支持多种转发模式,最常用的是直接路由(DR)、网络地址转换(NAT)和 IP 隧道(TUN)。理解它们的区别,是部署 LVS 的关键。

NAT 模式

NAT(Network Address Translation)模式最简单:调度器收到请求后,把目的地址从 VIP 改写成某台 RS 的地址,转发给 RS。RS 处理完,把响应发回调度器,调度器再把源地址从 RS 地址改回 VIP,返回给客户端。请求和响应都要经过调度器。

它的优点是对 RS 没有特殊要求,RS 可以是任意操作系统、任意网段,只要能路由到调度器。缺点是所有流量都要过调度器,调度器成为带宽瓶颈,只适合小规模。而且 RS 的默认网关必须指向调度器的内网地址,否则响应会绕过调度器,导致连接失败。

DR 模式

DR(Direct Routing,直接路由)模式是最常用的模式,也是性能最好的。它只改写请求数据包的 MAC 地址,不发往用户态也不做地址转换。调度器把请求转发给 RS,RS 直接用 VIP 作为源地址把响应发回给客户端,响应不经过调度器。

这样一来,调度器只处理请求方向的流量,响应直接由 RS 返回,吞吐量大幅提升,适合大流量、响应体大的场景(比如视频、图片)。代价是 RS 和调度器必须在同一物理网段,并且每台 RS 都要在回环接口上配置 VIP,同时抑制 ARP 响应,避免 RS 抢答 VIP 的 ARP 请求。

TUN 模式

TUN(IP Tunneling,IP 隧道)模式通过 IP 隧道把请求封装后转发给 RS,RS 解封后直接响应客户端。它支持 RS 跨网段、跨机房,比 DR 更灵活,但需要 RS 支持 IP 隧道协议,配置稍复杂,且在部分网络环境下封装开销和兼容性是问题。

三种模式对比

对比项 NAT DR TUN
是否改写 IP 是(双向) 否,只改 MAC 封装 IP 隧道
响应是否经过调度器 经过 不经过 不经过
性能 一般 最高 高
RS 与调度器同网段 不要求 要求 不要求
RS 配置复杂度 低 需配 VIP 与 ARP 需支持隧道
适用规模 小 大 中到大、跨机房
RS 操作系统 任意 支持隐藏 VIP 的系统 需支持隧道

经验上,同机房、追求性能优先选 DR;小规模、跨网段省事选 NAT;跨机房、需要灵活组网选 TUN。绝大多数生产环境用的是 DR。

调度算法:从轮询到最短期望延迟

调度算法决定请求如何分配给 RS。LVS 内置了十几种算法,常用的有以下几种。

静态算法不考虑后端当前负载:rr(轮询)依次分配;wrr(加权轮询)按权重分配,权重高的 RS 分到的请求多;dh(目的地址哈希)和 sh(源地址哈希)按地址做哈希,保证同一目标或同一来源固定到同一 RS。

动态算法会根据后端连接数、响应情况调整:lc(最少连接)把新请求交给当前连接数最少的 RS;wlc(加权最少连接)在 lc 基础上引入权重,是最常用的动态算法;sed(最短期望延迟)和 nq(永不排队)在 wlc 基础上做了改进;lblc(基于局部性的最少连接)适合缓存集群。

算法 类型 含义 适用场景
rr 静态 轮询 后端性能均匀
wrr 静态 加权轮询 后端配置不同
lc 动态 最少连接 连接耗时差异大
wlc 动态 加权最少连接 通用首选,性能不均
sh 静态 源地址哈希 会话保持、缓存亲和
dh 静态 目的地址哈希 缓存后端
sed 动态 最短期望延迟 长连接、大请求
lblc 动态 局部性最少连接 缓存集群

做后端性能差异明显的场景,wlc 往往是最稳的默认选择;需要会话保持又没有集中式会话存储时,可以用 sh,但要意识到 NAT 用户和扩缩容带来的偏差。

ipvsadm 基础命令

ipvsadm 是管理 LVS 的命令行工具。RHEL/CentOS/Rocky 系安装:

# RHEL / CentOS / Rocky 系
sudo dnf install -y ipvsadm

Debian/Ubuntu 系:

# Debian / Ubuntu 系
sudo apt update
sudo apt install -y ipvsadm

加载 IPVS 内核模块并查看状态:

sudo modprobe ip_vs
lsmod | grep ip_vs
sudo ipvsadm -L -n

添加一个虚拟服务和后端 RS,以 wlc 算法、DR 模式为例:

# 添加虚拟服务:VIP 192.0.2.100:80,使用加权最少连接
sudo ipvsadm -A -t 192.0.2.100:80 -s wlc

# 添加真实服务器,-g 表示 DR 模式,-w 表示权重
sudo ipvsadm -a -t 192.0.2.100:80 -r 192.0.2.21:80 -g -w 1
sudo ipvsadm -a -t 192.0.2.100:80 -r 192.0.2.22:80 -g -w 2

常用参数说明:-A 添加虚拟服务,-a 添加 RS,-D 删除虚拟服务,-d 删除 RS,-E 修改虚拟服务,-e 修改 RS。-t 指定 TCP,-u 指定 UDP。模式参数里 -g 是 DR,-m 是 NAT,-i 是 TUN。查看当前配置:

sudo ipvsadm -L -n --stats
sudo ipvsadm -L -n --rate

删除操作(风险提示: 删除虚拟服务会立即中断该 VIP 上的所有转发,请在维护窗口执行,并保留一份 ipvsadm -Sn 的导出以便恢复):

# 导出当前规则,便于回滚
sudo ipvsadm -Sn > /root/ipvs.rules.bak

# 删除某台 RS
sudo ipvsadm -d -t 192.0.2.100:80 -r 192.0.2.22:80

ipvsadm 的规则不会自动持久化,重启后丢失。RHEL 系可用 ipvsadm-save / ipvsadm-restore 保存和恢复:

sudo ipvsadm-save > /etc/sysconfig/ipvsadm
sudo systemctl enable ipvsadm

与 Keepalived 结合做高可用

单台 LVS 调度器本身是单点,一旦挂了整个入口就断了。所以生产环境通常用 Keepalived 管理 LVS 的 VIP 和规则:主备两台调度器,通过 VRRP 选主,主节点持有 VIP 并加载 LVS 规则,主节点故障时 VIP 漂移到备节点。

Keepalived 的配置里有一个 virtual_server 段,可以直接定义 LVS 虚拟服务和 RS,并在切换时自动增删规则。下面是主节点配置片段:

virtual_server 192.0.2.100 80 {
    delay_loop 6
    lb_algo wlc
    lb_kind DR
    protocol TCP

    real_server 192.0.2.21 80 {
        weight 1
        TCP_CHECK {
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 3
        }
    }
    real_server 192.0.2.22 80 {
        weight 2
        TCP_CHECK {
            connect_timeout 3
            nb_get_retry 3
            delay_before_retry 3
        }
    }
}

这段配置让 Keepalived 不仅管理 VIP,还管理 LVS 规则和后端健康检查。当 RS 探测失败时,Keepalived 会自动从 LVS 里摘除它,恢复后再加回来。多个 virtual_server 段可以定义多个 VIP 或端口。

后端 RS 在 DR 模式下要隐藏 VIP,避免 ARP 冲突。常见做法是在 RS 上把 VIP 配到 lo 回环接口,并抑制 ARP:

# 在每台 Real Server 上执行
sudo ip addr add 192.0.2.100/32 dev lo
sudo sysctl -w net.ipv4.conf.all.arp_ignore=1
sudo sysctl -w net.ipv4.conf.all.arp_announce=2
sudo sysctl -w net.ipv4.conf.lo.arp_ignore=1
sudo sysctl -w net.ipv4.conf.lo.arp_announce=2

要把这些参数持久化,RHEL 系写入 /etc/sysctl.d/99-lvs.conf,Debian/Ubuntu 也写入 /etc/sysctl.d/,然后执行 sudo sysctl --system。风险提示: 修改 ARP 相关内核参数会影响本机 ARP 行为,务必在所有 RS 上统一配置,改前记录原值以便回滚。

适用场景与局限

LVS 的优势在高并发、四层转发、大流量响应。典型的适用场景包括:作为 HTTP/HTTPS 入口的最外层分发,后端挂 Nginx 或 HAProxy;代理数据库连接池、Redis 集群的四层入口;大流量下载、视频、图片类业务。

它的局限同样明显。首先,纯四层无法按 URL、Host、Cookie 做路由,需要七层能力时必须配合 Nginx 或 HAProxy。其次,DR 模式要求 RS 与调度器同网段并正确隐藏 VIP,配置比 Nginx 复杂。再次,LVS 不理解应用协议,做不了 HTTPS 证书终结、请求改写、限流这类七层功能。最后,规则的持久化和运维自动化需要额外工作。

一个常见的架构是三层组合:最外层 LVS 做四层分发和抗量,中间层 Nginx 或 HAProxy 做七层路由和 HTTPS 终结,最内层是应用服务器。LVS 解决"扛住量",Nginx 解决"分得细",各司其职。

常见问题

LVS 和 Nginx 负载均衡能互相替代吗?

不能完全替代。LVS 是四层,性能高但功能少;Nginx 是七层,功能丰富但极端并发下不如 LVS。大型架构里两者常组合使用。

DR 模式下后端 RS 为什么要配 VIP 到 lo?

因为 RS 直接响应客户端时源地址是 VIP,配到 lo 上才能正确发送响应。同时要用 arp_ignore 和 arp_announce 抑制 ARP,防止 RS 抢答 VIP,造成地址冲突。

NAT 模式下连接建立失败怎么办?

常见原因是 RS 的默认网关没指向调度器,导致响应绕过了调度器。检查每台 RS 的路由,确保默认网关是调度器的内网地址。

ipvsadm 的规则重启后丢失怎么办?

LVS 规则默认不持久化。用 ipvsadm-save 保存到文件、ipvsadm-restore 恢复,或直接交给 Keepalived 的 virtual_server 配置管理。

什么时候不该用 LVS?

后端需要七层路由、HTTPS 终结、请求改写,或者规模不大、并发不高时,用 Nginx、HAProxy 更简单。LVS 的价值在极端并发和纯四层转发。

总结

  • LVS 是基于内核 IPVS 模块的四层负载均衡,调度器提供 VIP,后端是 RS,性能接近硬件负载均衡。
  • DR 模式性能最好但要求同网段并隐藏 VIP,NAT 简单但有带宽瓶颈,TUN 适合跨机房,生产多用 DR。
  • 调度算法里 wlc 是通用首选,性能均匀用 rr/wrr,会话或缓存亲和用 sh/dh,长连接大请求考虑 sed。
  • ipvsadm 负责规则管理,规则默认不持久化,配合 Keepalived 的 virtual_server 可同时实现高可用与健康检查。
  • LVS 强在扛量弱在功能,需要七层能力时应与 Nginx、HAProxy 组合,而不是指望 LVS 全包。