负载均衡原理:Nginx、LVS、DNS轮询,算法对比与选型

负载均衡这东西,说白了就是把流量分散到多台服务器上。你想想看,单点扛不住的时候怎么办?加机器。但加完机器,谁来分发请求?这就是负载均衡要解决的问题。

我最早接触大规模负载均衡,是在一个日活千万级的电商项目里。当时流量一上来,单台应用服务器直接打满,CPU报警。我们紧急上了Nginx做反向代理,才把流量扛住。后来随着规模扩大,又引入了LVS和DNS轮询。这三种方案各有各的战场,我分别讲讲。

三种核心负载均衡方案

1. DNS轮询

DNS轮询是最简单的方式。你在DNS服务器里为同一个域名配多个A记录,客户端解析时会随机拿到一个IP。这个方案优点是无成本,配置简单。但缺点也很明显:客户端会缓存DNS结果,流量分配不均匀;而且DNS服务器不知道后端服务器的健康状态,挂了照样发请求。

我曾经遇到过一个线上事故:某次扩容后,我改了DNS记录,想着流量能慢慢切过去。结果客户端缓存了旧的IP,新加的机器一直没流量。后来才知道,TTL设太长了,很多客户端根本不重新解析。从那以后,我调整重要业务的DNS TTL到60秒,并且配合健康检查一起用。

2. Nginx反向代理

Nginx是我最常用的七层负载均衡器。它工作在应用层,可以理解HTTP报文,实现更精细的路由,比如按URL、按Cookie、按Header分发。配置起来也直观:

upstream backend {
    # 加权轮询
    server 10.0.1.1:8080 weight=3;
    server 10.0.1.2:8080 weight=2;
    server 10.0.1.3:8080 backup;  # 备用节点
    keepalive 32;
}

server {
    listen 80;
    location /api/ {
        proxy_pass http://backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

Nginx还内置健康检查、连接超时、重试机制。我个人习惯在生产环境用 max_fails=3 fail_timeout=30s 来标记故障节点,避免频繁切换。

避坑指南:Nginx的keepalive连接数不要设太大,不然上游连接池会占用过多文件描述符。我记得有一次线上Nginx的 worker_connections 没调大,结果并发上来后直接报“too many open files”。

3. LVS(Linux Virtual Server)

LVS工作在四层(传输层),比Nginx更快。它直接在内核空间做包转发,不解析应用层协议,所以吞吐量极高。LVS有三种工作模式:

模式 转发方式 性能 典型场景
NAT模式 修改目标IP和端口 中等 中小规模,后端服务器可私有IP
TUN模式 IP隧道封装 高 跨机房、后端有公网IP
DR模式 直接修改MAC地址 最高 同机房高性能场景,后端必须配置VIP

我参与过的那个日活千万项目,最外层就是LVS/DR模式,直接扛住百万级并发。后端挂了两台Nginx做七层转发,再往后是应用服务器。这个分层架构,我画了一张图:

负载均衡分层架构图 负载均衡分层架构 客户端 (DNS轮询) LVS/DR (四层负载均衡) Nginx (七层负载均衡) Nginx (七层负载均衡) 应用服务器1 应用服务器2 应用服务器3 应用服务器4 DNS轮询 → LVS/DR(四层高吞吐) → Nginx(七层精细化路由) → 应用服务器池

负载均衡算法对比

不管是Nginx还是LVS,内部都有一组调度算法。选对算法,直接影响系统吞吐和响应时间。我整理了一张常用算法的对比表:

算法 特点 适用场景 常见实现
轮询 (Round Robin) 按顺序轮流,权重可调 服务器配置均匀、请求处理时间相近 Nginx upstream、LVS rr
最少连接 (Least Connections) 动态分配给当前连接数最少的节点 长连接、请求处理时间差异大 Nginx least_conn、LVS lc
IP哈希 (IP Hash) 根据客户端IP哈希,保证同一IP固定发到同一台服务器 需要会话保持(Session Stickiness) Nginx ip_hash、LVS sh
URL哈希 根据请求路径或参数做哈希 缓存命中优化、API网关路由 Nginx hash指令
加权轮询 (Weighted RR) 按权重分配比例,适合异构服务器 服务器性能不同时 Nginx weight参数、LVS wrr
最少响应时间 选择响应时间最短的节点 需要低延迟的业务 Nginx 商业版、第三方模块

选型建议:

  • 业务场景简单、服务器性能一致 → 轮询就行,配置最低。
  • 请求处理时间差异大 → 最少连接,能自动均衡实时负载。
  • 需要会话保持 → IP哈希,但要小心源IP变化导致负载不均。我有个项目用了哈希,结果某个运营商出口IP特别集中,导致一台服务器被压垮。
  • 七层路由(按域名、路径分发) → Nginx;纯四层加速 → LVS。

实战选型流程

接下来我分享一套我自己总结的选型流程。你不必死记硬背,理解思路就好。

  1. 看吞吐量:如果预估并发连接数超过10万,优先考虑LVS/DR。Nginx单机在普通硬件上能扛到几万并发,再高就需要多实例或前置LVS。
  2. 看协议:HTTP/HTTPS/WebSocket业务用Nginx可以灵活路由;TCP/UDP业务用LVS更好。DNS轮询只适合入口层简单分流。
  3. 看需求:需要灰度发布、蓝绿部署、A/B测试?必须用七层负载均衡(Nginx)。只需要简单的流量分发?用LVS或DNS轮询就够了。
  4. 看运维:团队如果熟悉Nginx配置,可以全栈用Nginx+ keepalived做高可用。如果对内核调优有经验,LVS可以发挥极致性能。

我曾经踩过一个坑:有个项目直接用LVS做七层业务分发,结果后端应用需要获取客户端真实IP。LVS/DR模式下后端看到的源IP是LVS的IP,必须通过TOA模块或者proxy protocol才能透传。当时没注意,后来查日志全是一个IP,排查问题花了半天。所以选型时一定要考虑网络拓扑对业务的影响。

小结

负载均衡选型没有银弹。DNS轮询简单但粗糙,LVS高效但底层,Nginx灵活但吃性能。在实际项目中,我通常把它们组合使用:最外层DNS轮询做多机房或多云分发,中间用LVS做四层流量接入,内部用Nginx做七层路由。三层各司其职,这才是我认为比较完善的架构。