负载均衡器详解:在VPS上配置Nginx

当您的网站流量增长,单台服务器已无法承载所有传入请求——或者当那台服务器宕机并拖垮整个网站时,负载均衡器就是解决方案。它位于后端服务器前端,自动将传入请求分发到所有服务器,即使某台服务器故障,也能保持服务持续在线。

本指南将介绍什么是负载均衡器、如何选择算法,以及如何从零开始在Ubuntu VPS上将Nginx配置为负载均衡器。

前提条件:至少2台Ubuntu 20.04/22.04 VPS实例(1台负载均衡器 + 至少2台后端服务器),对所有服务器拥有SSH访问权限,并在所有服务器上安装了Nginx。

什么是负载均衡器?

负载均衡器是一种设备或软件,充当所有传入流量的单一入口点,然后根据所选算法将每个请求转发到多台后端服务器之一。用户始终连接到负载均衡器,而不是直接连接到后端服务器。

对比项无负载均衡器有负载均衡器
单点故障存在——服务器宕机即网站下线不存在——流量自动切换到健康服务器
流量承载能力受限于单台服务器规格分散到多台服务器
维护必须使网站下线下线一台服务器、部署、再重新加入
扩展方式仅垂直扩展(升级配置)水平扩展(增加服务器数量)

负载均衡算法

算法决定了负载均衡器如何决定将每个请求发送到哪台后端服务器。请根据您的工作负载进行选择:

1. 轮询算法(默认)

请求按顺序循环分发:A → B → C → A → B → C → … 当所有服务器配置相似且每个请求所需资源相近时效果最佳。

2. 最少连接算法

将每个新请求发送到当前活跃连接数最少的服务器。适用于长连接请求(如API调用、文件上传),部分请求耗时远长于其他请求的场景。

3. IP哈希算法

使用客户端IP地址决定将请求发送到哪台服务器。相同的IP始终路由到同一台服务器(会话持久性)。适用于将会话存储在服务器内存而非共享Redis或数据库的应用程序。

4. 加权轮询算法

带权重的轮询算法——配置较高的服务器接收更多请求。例如,服务器A(weight=3)处理每4个请求中的3个,服务器B(weight=1)处理每4个中的1个。

在Ubuntu VPS上搭建Nginx负载均衡器

Nginx原生支持负载均衡,无需额外软件。本示例使用3台VPS实例:

实例角色示例IP
VPS-LB负载均衡器(Nginx)10.0.0.1
VPS-B1后端服务器1(Web应用)10.0.0.2
VPS-B2后端服务器2(Web应用)10.0.0.3

步骤1 — 在负载均衡器上安装Nginx

SSH连接到VPS-LB并安装Nginx:

sudo apt update && sudo apt install nginx -y
sudo systemctl enable nginx
sudo systemctl start nginx

步骤2 — 创建upstream块

为负载均衡器创建新的站点配置文件:

sudo nano /etc/nginx/sites-available/load-balancer

粘贴以下内容(轮询为默认算法):

upstream backend_pool {
    # Round Robin (default) — uncomment to change algorithm
    # least_conn;     ← Least Connections
    # ip_hash;        ← IP Hash (Session Persistence)

    server 10.0.0.2:80;
    server 10.0.0.3:80;
}

server {
    listen 80;
    server_name yourdomain.com www.yourdomain.com;

    location / {
        proxy_pass http://backend_pool;
        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;
    }
}

为什么需要proxy_set_header?这些标头将真实客户端IP转发给后端服务器。如果没有这些标头,后端日志中每个请求只会显示负载均衡器的IP,使调试和数据分析毫无意义。

步骤3 — 启用配置

# Create symlink to enable
sudo ln -s /etc/nginx/sites-available/load-balancer /etc/nginx/sites-enabled/

# Test configuration syntax
sudo nginx -t

# Reload Nginx (no downtime)
sudo systemctl reload nginx

步骤4 — 使用加权轮询

如果VPS-B1的配置高于VPS-B2,可以为其分配更高权重以处理更多流量:

upstream backend_pool {
    server 10.0.0.2:80 weight=3;  # 处理每4个请求中的3个
    server 10.0.0.3:80 weight=1;  # 处理每4个请求中的1个
}

步骤5 — 配置健康检查

Nginx可以检测后端服务器何时无响应,并暂时停止向其发送流量:

upstream backend_pool {
    server 10.0.0.2:80 max_fails=3 fail_timeout=30s;
    server 10.0.0.3:80 max_fails=3 fail_timeout=30s;
}
选项含义
max_fails=3连续3次健康检查失败后将该服务器标记为宕机
fail_timeout=30s停止发送流量30秒后重试

添加proxy_next_upstream以实现更精细的被动健康检查:

location / {
    proxy_pass http://backend_pool;
    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;

    # 如果后端返回错误,立即尝试下一台服务器
    proxy_next_upstream error timeout http_502 http_503 http_504;
    proxy_connect_timeout 5s;
    proxy_read_timeout 60s;
}

步骤6 — 为负载均衡器添加SSL

用户仅连接到负载均衡器,因此在此处安装SSL。后端服务器在私有网络上通过HTTP通信(SSL在负载均衡器处终止):

# 安装Certbot以使用Let's Encrypt
sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com

Certbot会自动更新您的Nginx配置以处理HTTPS并设置自动续期。

SSL终止说明:当后端服务器位于同一数据中心的私有网络中时,这种在负载均衡器处解密HTTPS、然后转发HTTP到后端的方式是安全的。如果后端位于不同的地理位置,请改为使用端到端HTTPS。

步骤7 — 测试流量分配

在每台后端服务器上放置一个简单的测试脚本,以确认负载均衡器路由正常:

# 在VPS-B1上
echo '<?php echo "Response from: " . gethostname(); ?>' > /var/www/html/hostname.php

# 在VPS-B2上
echo '<?php echo "Response from: " . gethostname(); ?>' > /var/www/html/hostname.php

然后从本地机器多次访问该接口:

for i in {1..6}; do curl -s http://yourdomain.com/hostname.php; echo; done

您应该看到响应在vps-b1和vps-b2之间交替出现。

故障切换测试 — 让一台后端下线

# 停止VPS-B1上的Nginx以模拟服务器故障
sudo systemctl stop nginx

# 您的网站应仍从VPS-B2正常响应
curl http://yourdomain.com/

预期结果:网站保持在线,由VPS-B2提供服务。Nginx根据max_fails设置检测到VPS-B1停止响应,并自动停止向其发送流量,直至其恢复。

无停机添加新后端服务器

要添加新的后端服务器,只需更新配置并重载Nginx——无需重启:

# 将VPS-B3加入服务器池
upstream backend_pool {
    server 10.0.0.2:80 max_fails=3 fail_timeout=30s;
    server 10.0.0.3:80 max_fails=3 fail_timeout=30s;
    server 10.0.0.4:80 max_fails=3 fail_timeout=30s;  # ← 新服务器
}

# 零停机重载
sudo nginx -t && sudo systemctl reload nginx

监控日志

# 实时查看访问日志
sudo tail -f /var/log/nginx/access.log

# 查看错误日志
sudo tail -f /var/log/nginx/error.log

后续步骤:负载均衡器运行后,下一个挑战是共享状态。所有后端需要访问相同的会话(Redis)、相同的上传文件(NFS或对象存储)以及相同的数据库。建议使用Keepalived为负载均衡器本身添加高可用性,防止其成为新的单点故障。

启用Nginx状态模块进行实时监控

Nginx内置了stub_status模块,可提供实时连接统计信息。在负载均衡器的服务器配置中添加以下location块以安全启用该功能:

server {
    listen 80;
    server_name yourdomain.com;

    location /nginx_status {
        stub_status on;
        allow 127.0.0.1;       # 仅允许本地访问
        allow 10.0.0.0/24;     # 允许私有网络
        deny all;              # 阻止所有其他访问
    }

    location / {
        proxy_pass http://backend_pool;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

重载Nginx后,查询状态接口:

curl http://localhost/nginx_status

典型响应如下:

Active connections: 45
server accepts handled requests
 1024 1024 3891
Reading: 0 Writing: 3 Waiting: 42
字段 含义
Active connections当前正在处理的连接总数
accepts自Nginx启动以来接受的连接总数
handled已处理的连接数(应与accepts相等)
Reading正在读取请求头
Writing正在向客户端发送响应
Waiting空闲的keep-alive连接,等待新请求

使用Redis共享会话存储解决会话问题

在现有Web应用程序中引入负载均衡器时,最常见的问题是会话不一致。用户登录后被路由到后端1,下一个请求却到达了不了解该会话的后端2,用户因此被强制退出登录。正确的解决方案是使用Redis作为所有后端服务器共同读写的会话存储中心。

安装Redis(在专用VPS或负载均衡器上)

sudo apt install redis-server -y
sudo systemctl enable redis-server

# 允许后端连接——编辑 /etc/redis/redis.conf
# 修改:bind 127.0.0.1 → bind 127.0.0.1 10.0.0.1
sudo systemctl restart redis-server

在每台后端上配置PHP使用Redis会话

# 在每台后端上编辑 /etc/php/8.x/fpm/php.ini
session.save_handler = redis
session.save_path = "tcp://10.0.0.1:6379?auth=yourpassword"

效果:用户只需登录一次,无论后续请求由哪台后端服务器处理,都能保持认证状态。使用共享Redis会话后,无需再使用IP哈希——轮询算法均衡分配负载,同时会话在整个服务器池中保持一致。

负载均衡器与反向代理——有何区别?

Nginx既可以充当反向代理,也可以充当负载均衡器。这两个术语相关但有所区别:

特性 反向代理 负载均衡器
主要用途 将请求转发到单台后端 将请求分发到多台后端
后端数量 通常为一台 两台或更多
故障切换 无——后端宕机即网站下线 自动——流量切换到健康服务器
主要优势 SSL终止、缓存、压缩 高可用性、水平扩展能力
Nginx配置 proxy_pass http://127.0.0.1:3000 upstream块 + proxy_pass

实际上,Nginx的负载均衡器就是带有upstream服务器池的反向代理。两者的区别在于您代理到多少台后端以及是否涉及分发算法。

泰国与新加坡VPS的推荐架构

AsiaGB在泰国和新加坡均提供VPS,让您能够轻松构建多地区负载均衡设置,以低延迟服务东南亚的用户:

角色 推荐配置 起价
负载均衡器(LB) 泰国VPS入门款——CPU占用低,仅处理路由 500泰铢/月
后端1(TH) 泰国VPS——为本地用户提供低延迟 500泰铢/月
后端2(SG) 新加坡VPS——覆盖东南亚及全球流量 500泰铢/月

多地区注意事项:当后端服务器跨越不同数据中心(泰国和新加坡)时,会话和数据库必须通过网络同步。建议使用Redis Cluster或MySQL主从复制,如果跨地区延迟导致会话同步延迟,可考虑使用IP哈希算法。

需要VPS搭建负载均衡?

AsiaGB在泰国和新加坡提供拥有完整root权限的VPS,起价500泰铢/月,随时按需扩展服务器池。

查看所有VPS套餐 →