用多台 VPS 搭负载均衡:Nginx/HAProxy/Keepalived 入门

一台顶不住就上多台。用 Nginx/HAProxy 做七层/四层转发,Keepalived 解决单点,讲清从零到高可用的思路,并说清什么时候其实不需要它。

一台 VPS 顶不住流量的时候,最朴素的做法是“再加一台”。但加机器只是第一步,真正的难点是怎么让流量均匀地流到每台机器上、某一台挂了能自动摘掉、负载均衡器自己也不能成为单点。这篇文章用 Nginx、HAProxy 和 Keepalived 三件套,带你从零理解多台 VPS 的负载均衡,从四层 / 七层的区别讲到高可用,不堆术语,只讲能落地的思路。

延伸阅读

更多相关攻略推荐:【API 中转 02】ChatGPT/Claude API 中转 V量化/EA 交易要低延迟:跑外汇机器人该选哪台 VPS?就近机房实测2026 多语言/多区域 SEO 技术栈:hreflang+CDN Tailscale 连上了却卡成狗?自建 DERP/ZeroTier2026 VPS 选购决策树与白皮书:一张图看懂怎么买

一、为什么单机不够用,需要负载均衡

很多站长从一台 VPS 起步:装个 LNMP,把网站丢上去,日子过得挺好。直到某天流量上来,CPU 常年飙到 80% 以上;或者更糟,机房抽风、母鸡宕机,整站直接打不开。这时候再想去扩容,已经不是加内存加核就能解决的事——你真正需要的是把流量摊到多台 VPS 上。单台 VPS 有三个绕不开的硬伤:

  • 性能天花板:共享 vCPU 超售严重,老款 Xeon E5 单核弱,而建站类应用(WordPress、PHP、MySQL、TLS 握手)偏偏最吃单核性能,流量一涨就顶不住;
  • 单点故障:这台机器挂了,业务全停,别无退路;
  • 无法滚动更新:你想升级程序、换证书,只能停机维护,用户跟着遭殃。

负载均衡把多台 VPS 编成一组后端,前端用一台机器做流量入口,三件事同时解决——性能横向扩展、坏一台自动摘流、更新可以一台台来不中断服务。本文不谈云厂商那套托管负载均衡器,只聊怎么用两台、三台便宜 VPS 自己搭一套高可用架构。

二、先搞清楚:L4 和 L7 负载均衡差在哪

负载均衡按工作的网络层次分,最常见的是四层(L4)和七层(L7)。

L4 工作在传输层(TCP / UDP),负载均衡器只看到“连接从哪个 IP 发到哪个 IP、哪个端口”,不解析里面的内容。它把整条 TCP 连接原样转发给后端,开销小、并发高,适合数据库、游戏服务器、Redis 这类非 HTTP 协议。

L7 工作在应用层(HTTP / HTTPS),负载均衡器会解析请求内容,能根据 URL 路径、域名、Cookie 来路由。比如把 /api 转到 API 服务器、把静态请求转到另一组机器。代价是要解析协议、可能还要做 TLS 终止,CPU 和内存开销更大,但能做更精细的流量控制、会话保持和改写。

简单说:L4 快但粗,L7 慢一点但聪明。实际项目里经常是 L4 做入口、L7 做业务路由,或者两者混着用——同一个 HAProxy 实例里完全可以为 80 端口配 http 模式、为 3306 端口配 tcp 模式。经验法则:纯 Web 站用 L7;要转发非 HTTP 流量或追求极致吞吐,用 L4。HAProxy 两边都能做,Nginx 通过 stream 模块也能做 L4,但日常大家还是拿它做 L7。

对预算型 VPS 来说,这个选择还有一个现实意义:L4 转发几乎不消耗 CPU,你那台小机器如果只是做纯 TCP 转发,能腾出更多资源给业务;而 L7 要解析 HTTP、做 TLS 卸载,会更吃 CPU。所以如果你后端跑的是 HTTPS、又想在负载均衡器上统一做证书(TLS termination),得掂量一下均衡器那台机器的配置,别让它成了新的瓶颈。预算紧张时,常见的折中是:后端之间用内网 HTTP 通信,只在最外层均衡器上做一次 TLS 终止,减少重复加解密的开销。

三、用 Nginx 做七层转发(配置片段)

Nginx 的 upstream 模块天生就能做 HTTP 负载均衡。最基础的轮询配置:

http {
  upstream backend {
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;
    server 192.168.1.12:8080;
  }
  server {
    listen 80;
    location / {
      proxy_pass http://backend;
      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-Forwarded-Proto $scheme;
    }
  }
}

不指定算法时默认就是轮询(round-robin),请求一台接一台分下去。Nginx 还支持几种常用策略:

  • least_conn:新请求发给当前连接数最少的后端,比盲轮询更公平,适合某些请求耗时差异大的场景;
  • ip_hash:按客户端 IP 做哈希,保证同一来源总是落到同一台机器,实现会话保持;
  • weight=数字:给机器加权,性能好的机器多分点流量,比如 weight=5 的机器大约拿到 5/8 的流量。

健康检查方面,Nginx 开源版做的是“被动”检查:某后端连续失败 max_fails 次(默认 3)、在 fail_timeout 秒(默认 30)内就被暂时踢出,恢复后再慢慢加回来。还可以用 backup 标记一台备用机,只有主机器全挂时才顶上;用 down 可以临时把它移出轮询而不删配置。这些都在 upstream 块里一行写完,门槛很低。另外建议在 location 里加一行 proxy_next_upstream error timeout http_502 http_503,它定义了哪些情况下 Nginx 会换一台后端重试,而不是直接把错误甩给客户端。

四、用 HAProxy 做四层 / 七层(配置片段)

HAProxy 是更专业的负载均衡软件,四层和七层都擅长,还带丰富的健康检查和统计页面。先在独立的入口 VPS 上装 HAProxy(一台 1 核的小机器就够):

sudo apt install haproxy -y
sudo cp /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.bak
sudo haproxy -f /etc/haproxy/haproxy.cfg -c  # 改完先校验语法
sudo systemctl restart haproxy

一个典型的七层配置(含轮询、主动健康检查、Cookie 会话保持和一台备用机):

frontend http_front
  bind *:80
  mode http
  default_backend web_servers

backend web_servers
  mode http
  balance roundrobin
  option httpchk GET /health
  http-check expect status 200
  cookie SRVID insert indirect nocache
  server web1 192.168.1.11:8080 check cookie s1 inter 5s fall 3 rise 2
  server web2 192.168.1.12:8080 check cookie s2 inter 5s fall 3 rise 2
  server web3 192.168.1.13:8080 check cookie s3 backup

frontend 定义“监听哪里、用什么模式”,backend 定义“后端机器组和算法”。check 开启健康检查,inter 5s fall 3 rise 2 表示每 5 秒探一次、连错 3 次摘流、连对 2 次重新入池;cookie SRVID insert 让 LB 给浏览器种一个 SERVERID,之后同一用户固定回那台,实现粘性会话;backup 那台只在前面全挂时才顶上。mode http 就是七层,可以基于 URL、Host 头、Cookie 路由;把 mode 改成 tcp,就变成四层,适合转发 MySQL、Redis 这类非 HTTP 流量:

frontend mysql_front
  bind *:3306
  mode tcp
  default_backend mysql_servers

backend mysql_servers
  mode tcp
  balance roundrobin
  option mysql-check user haproxy
  server db1 192.168.1.21:3306 check
  server db2 192.168.1.22:3306 check

HAProxy 的健康检查是“主动”的:它真的按 httpchk 去探后端的 /health,期望返回 200;探不到就把它摘掉。想实时看状态,加一段 stats 面板:

listen stats
  bind *:8404
  stats enable
  stats uri /stats
  stats refresh 10s

打开 8404 端口,每台后端是绿(UP)还是红(DOWN)一目了然。HAProxy 的 stats 页面能实时看到每台机器的连接数、会话速率和健康状态,排障特别方便。算法上除了 roundrobin,还有 leastconn(适合长连接、WebSocket、API)、source(按源 IP 保持会话)、uri(按请求路径哈希,适合缓存场景)等。对于只做 HTTP 且已经在跑 Nginx 的站点,直接用 upstream 就够了;想要更强的调度粒度和观测能力,HAProxy 更顺手。

五、Nginx 还是 HAProxy?一张表看懂

这是被问得最多的问题。一句话结论:HAProxy 是专为负载均衡而生的纯 LB,Nginx 是顺带能负载均衡的 Web 服务器。下面这张表把关键差异摆清楚:

维度HAProxyNginx upstream
出身定位专职负载均衡器Web 服务器兼做 LB
L4 能力极强,连接排空 / ACL 路由成熟有 stream 模块,但偏弱
健康检查主动 HTTP / TCP / agent 检查开源版仅被动检查,主动需 Plus
会话保持Cookie 插入、source 哈希ip_hash、hash 指令
实时监控Stats 面板业界最佳需第三方或 Plus
静态缓存不擅长内置缓存、gzip、Brotli
配置风格flat 结构,显式可读嵌套块,熟悉但易踩继承坑

简单做法:如果你已经是 Nginx 用户、后端不多、要顺手带缓存,直接上 Nginx upstream 最省事。如果你要精确流量控制、做 TCP 转发、要实时看每台机器状态,或者后端有十台以上,上 HAProxy。进阶玩法是两个都用——Nginx 放边缘做 SSL 终结和缓存,HAProxy 在后排做后端分发,各取所长。

六、会话保持:cookie / ip_hash / 共享存储

如果你的应用把登录态存在本地文件或内存里,用户被轮到另一台机器就会掉登录。三种解法:

  • Cookie 插入(HAProxy):LB 给浏览器种一个 SERVERID,之后同一用户固定回那台。配置见上文 cookie SRVID insert
  • ip_hash(Nginx):按客户端 IP 哈希选机器。缺点是在 NAT 或移动网络下,大量用户共用一个出口 IP,会全挤到一台。
  • 共享会话存储(推荐):用 Redis 或 Memcached 存 session,后端无状态,随便哪台都能处理。这是最干净的架构,也最利于水平扩展。

能上共享存储就别依赖粘性会话,后者会让流量分布不均,扩缩容时还会丢会话。

七、Keepalived + VRRP:别让负载均衡器自己成单点

前面无论 Nginx 还是 HAProxy,都还是“一台”负载均衡器。它一旦崩了,后面十台机器全跟着看不见——这就是单点故障(SPOF)。Keepalived 用 VRRP 协议解决这个问题:两台负载均衡器共享一个虚拟 IP(VIP),平时 MASTER 持有 VIP,BACKUP 在旁边监听;MASTER 一挂,BACKUP 在 2–3 秒内把 VIP 抢过来,用户只感觉到一瞬闪断。

一个最简的 MASTER 配置:

vrrp_instance VI_1 {
  state MASTER
  interface eth0
  virtual_router_id 51
  priority 100
  advert_int 1
  authentication {
    auth_type PASS
    auth_pass secret123
  }
  virtual_ipaddress {
    192.168.1.100/24 dev eth0
  }
}

BACKUP 节点几乎一样,只改两处:state BACKUP、priority 90(比 MASTER 低)。两边 virtual_router_id 必须相同,auth_pass 也必须相同,否则选不上。注意一个小坑:负载均衡器要绑定一个“此刻可能还不存在”的 VIP,所以两个节点都得开 net.ipv4.ip_nonlocal_bind=1,否则进程启动时会因为绑不上 IP 而报错。

更稳妥的做法是加 track_script:写个脚本探 Nginx / HAProxy 进程还活着没,活着权重不减,挂了就把本机 priority 减 50,自动让出 VIP。这样哪怕操作系统没崩、只是负载均衡进程死了,也能平滑切走。VRRP 默认开启抢占(preemption),原 MASTER 恢复后会把 VIP 抢回来;如果担心来回切换造成抖动,可以配 nopreempt 让 BACKUP 升主后不主动让位。

有一点要提前提醒:不少云平台(尤其是某些按流量计费的 VPS)默认禁止 VRRP 的组播包,BACKUP 收不到 MASTER 的心跳就会脑裂或切换失败。遇到这种情况,要么改用 Keepalived 的单播(unicast_peer)模式,要么干脆用厂商自带的负载均衡产品(如云上的 LB 实例)代替自建 VIP。自建高可用最适合可控的网络环境,别在受限环境里硬刚,否则省下的钱会加倍还给排障时间。

八、健康检查与优雅摘流(实战收尾)

健康检查是负载均衡的灵魂。光做 TCP 端口探测不够——端口开着、进程却卡死的情况太常见。正确做法是让后端暴露一个 /health 接口,HAProxy 用 option httpchk 发 GET,期望返回 200。后端可以这样写:

# 在每台后端 Nginx 上
location = /health {
  access_log off;
  add_header Content-Type text/plain;
  return 200 "ok";
}

HTTP 探活比纯 TCP 更准,能发现“进程卡死但端口还开着”的情况;数据库等非 HTTP 服务才用 TCP 探端口。探测间隔别太激进,5 到 10 秒一次足够,fall / rise 的阈值要有容错,避免偶发抖动误摘流。

高可用不是配完就完事,关键是“摘流要优雅”。后端要维护时,别直接 kill 进程——那样正在进行的请求会报错、用户会看到 502。Nginx / HAProxy 都支持把某台后端标记为 drain(排干):不再接新连接,但等已有连接自然结束再下线。HAProxy 还能通过 socat 连 stats socket 动态操作:

echo "set server web_servers/web1 state drain" | sudo socat stdio /var/run/haproxy.sock

这行命令把 web1 优雅摘出,维护完再 ready 加回:

echo "set server web_servers/web1 state ready" | sudo socat stdio /var/run/haproxy.sock

配合主动健康检查,整个集群能在无人值守下自动绕开坏机器、自动恢复好机器。Nginx 侧可以用 max_fails 与 fail_timeout 控制被动摘流,HAProxy 侧用 check inter(探测间隔)、rise(几次算健康)、fall(几次算故障)精细调节。配合 HAProxy 运行时 API 可以做到不停服务地摘下某台机器做维护,比直接改配置文件再 reload 更平滑。

配完之后怎么确认真的生效了?最简单的是在客户端用循环 curl 打几十次,观察后端是否轮流响应(可以让每台机器返回一个带自己 IP 的标识);Nginx 侧把 $upstream_addr 写进访问日志,HAProxy 侧直接看 stats 页面,就能确认流量确实被打散了。上线前最好手动杀掉一台后端,看请求是否自动避开它;再模拟一次 MASTER 宕机,看 VIP 是否在几秒内漂到 BACKUP。这两步演练能做到,才算真正从零走到了高可用,而不是只是把配置写对了。

总结一下思路:先用 Nginx 或 HAProxy 把流量分到多台 VPS(四层还是七层看你跑的协议),再用 Keepalived 给负载均衡器本身加一层 VIP 漂移消除单点,最后靠健康检查 + 优雅摘流让集群能自愈。从零到高可用,核心就是这三步,不神秘,也花不了多少配置。

九、多台 VPS 的取舍与成本

负载均衡不是免费午餐,它至少多吃一台入口机,还要考虑后端互联。几个现实考量:

  • 内网互通:同机房的后端尽量走内网 IP 互访,流量不计费、延迟低。RackNerdVultrDMIT 这类商家不同机房之间可能没有免费内网,跨区只能用公网 IP,记得算流量成本。
  • IPv4 附加费:2026 年 IPv4 枯竭,单 IP 租用约 0.30 到 0.55 美元/月,不少商家每台机器额外收 2 到 3 美元 IP 费。规划后端数量时把这钱算进去。
  • 入口机要稳:LB 是咽喉,建议选网络稳、线路好的机器。面向大陆用户可考虑 DMITCN2 GIA(AS4809)线路,延迟 130 到 160ms 最稳;预算紧可以用 RackNerd 年付十几美元的套餐做入口,再把算力分散到多台便宜后端。
  • 别被首年价骗:很多特价续费翻倍,规划长期架构要看续费价,别按首年价估成本。

一个务实的组合:一台 VultrDMIT 做入口 LB(要稳),后面挂两到三台 RackNerd 年付机做应用后端,用内网或同机房公网串联。总成本可能也就每月几美元到十几美元,却换来了单机没有的可用性和扩展弹性。最后别忘了监控与告警:LB 把故障藏在了背后,你反而更难第一时间发现某台后端悄悄挂了。把 HAProxy 的 stats socket 接上 Prometheus,或者用 Nginx 的 stub_status 配合外部探测,后端掉一台就要有提醒,别等用户投诉才后知后觉。备份策略也要覆盖到 LB 本身——它的配置文件虽小,但丢了就得手忙脚乱重新写。

十、什么时候其实不需要负载均衡

月访问量几千、单机 CPU 常年低于 30%、业务停几分钟没人 care,那真没必要上 LB,先把单机优化好、做好定时备份更划算。负载均衡解决的是“扩展性”和“可用性”,不是“性能不好”——慢是因为程序烂或配置差,加机器只是分摊,不治本。

延伸阅读:如果是第一次上手 VPS,先看 VPS 新手入门指南;部署后别忘了基础安全,参考 VPS 安全基础;关于选机器和带宽规划,见 VPS 带宽与流量指南;关于架构与基础设施的更多深潜指南,请前往 VPS 主题导读中心 (Hub)