在 Nginx 中配置負載均衡,主要是通過 upstream 模塊來定義一組後端服務器,並選擇合適的負載均衡算法,然後在 location 塊中通過 proxy_pass 指令將請求轉發給這個服務器組。

下面這個表格整理了 Nginx 常用的負載均衡算法,你可以根據業務場景快速選擇。

算法名稱

配置指令

核心邏輯

適用場景

輪詢 (Round Robin)

默認,無需配置

請求按時間順序逐一分配到不同後端服務器。

後端服務器性能相近的無狀態服務。

加權輪詢 (Weighted Round Robin)

weight

在輪詢基礎上,通過權重決定服務器接收請求的比例

後端服務器性能不均,希望高性能服務器處理更多請求。

IP哈希 (IP Hash)

ip_hash

根據客户端IP的哈希值分配請求,同一IP的請求總是發往同一台服務器。

需要會話保持 (session persistence) 的場景,如用户登錄狀態。

最少連接 (Least Connections)

least_conn

將新請求分配給當前活躍連接數最少的服務器。

後端服務器處理請求的耗時長短不一,希望實現更公平的負載,如長連接應用。

URL哈希 (URL Hash)

hash $request_uri

根據請求URL的哈希值分配請求,同一URL的請求總是發往同一台服務器。

主要為了提高後端緩存命中率,需要安裝第三方模塊

Fair (響應時間)

fair

根據後端服務器的響應時間來分配請求,響應時間短的優先分配。

後端服務器性能波動較大,希望更智能地進行負載,需要安裝第三方模塊

⚙️ 一、如何配置負載均衡

以下是配置 Nginx 負載均衡的基本步驟和一個配置示例。

基本步驟
  1. 安裝 Nginx:確保你的服務器上已經安裝了 Nginx。
  2. 編輯配置文件:打開 Nginx 的配置文件,通常位於 /etc/nginx/nginx.conf/etc/nginx/conf.d/default.conf
  3. 添加 Upstream 塊:在 http 塊內,使用 upstream 指令定義一個後端服務器組。
  4. 配置代理轉發:在 server 塊下的 location 中,使用 proxy_pass 指令指向 upstream 組的名稱。
  5. 檢查並重啓:執行 sudo nginx -t 測試配置語法是否正確,然後使用 sudo systemctl restart nginx 重啓 Nginx 使配置生效。
配置示例

以下是一個結合了加權輪詢最少連接算法的配置示例,幷包含了一些常用的反向代理參數。

http {
    upstream backend_servers {
        # 使用'least_conn'最少連接算法
        least_conn;
        # 定義後端服務器列表並設置權重
        server backend1.example.com weight=3;
        server backend2.example.com weight=2;
        server backend3.example.com weight=1;
        # 可選的服務器狀態參數
        # server backup.example.com backup;  # 標記為備份服務器,其他服務器不可用時才啓用
        # server down.example.com down;      # 標記為永久停機
    }
    server {
        listen 80;
        server_name yourdomain.com;
        location / {
            # 將請求轉發到上游服務器組
            proxy_pass http://backend_servers;
            # 設置一些重要的反向代理頭信息
            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;
        }
    }
}
  • 服務器健康檢查:Nginx 開源版默認只支持被動的健康檢查(當請求失敗時標記服務器不可用)。更強大的主動健康檢查功能需要 Nginx Plus 或第三方模塊(如 ngx_http_upstream_check_module)來實現。
  • 會話保持:如果選擇了 ip_hash 算法,需要注意當後端服務器宕機或增刪時,哈希結果可能會改變,影響會話一致性。此外,ip_hashbackup 參數不能同時配置。
  • 故障轉移:可以使用 proxy_next_upstream 指令定義在何種情況下(如超時、後端返回500錯誤等)將請求轉發到下一台服務器,從而實現故障轉移。
2.1 存在的問題以及解決方案

1.解決會話一致性問題

問題描述:

  • 用户登錄狀態丟失(會話數據存儲在後端實例內存中)
  • 購物車內容不一致
  • 表單重複提交

解決方案:

# 方法1:IP Hash策略(簡單但不完美)
upstream backend_servers {
ip_hash;
server 192.168.1.10:8080;
server 192.168.1.11:8080;
}
# 方法2:Cookie-based會話保持(Nginx Plus)
upstream backend_servers {
sticky cookie srv_id expires=1h domain=.example.com path=/;
server 192.168.1.10:8080;
server 192.168.1.11:8080;
}

更好的解決方案:

  • 使用Redis/Memcached等外部會話存儲
  • 採用JWT等無狀態身份驗證

2. 文件上傳與存儲一致性問題

問題描述:

用户上傳的文件只存在於某個特定實例
後續請求可能被路由到沒有該文件的實例

# 使用共享存儲方案
# 1. 網絡文件系統(NFS)
mount -t nfs 192.168.1.100:/shared_storage /app/uploads
# 2. 對象存儲(推薦)
# 直接使用AWS S3、阿里雲OSS等雲服務

3. 配置管理與一致性
問題描述:

  • 不同實例配置不一致
  • 環境變量差異
  • 代碼版本不同步
    這裏解決方案是使用docker構建應用。
# 使用Docker + 配置管理工具
version: '3'
services:
app:
image: your-app:${VERSION}
environment:
- DATABASE_URL=${DB_URL}
- REDIS_URL=${REDIS_URL}
volumes:
- shared_uploads:/app/uploads

4. 數據庫連接瓶頸
問題描述:

-- 每個應用實例都創建數據庫連接
-- 可能導致數據庫連接數爆滿
SHOW PROCESSLIST; -- 查看當前連接數

解決方案:

# 連接池優化 + 數據庫代理
upstream backend_servers {
server 192.168.1.10:8080 max_conns=100;  # 限制單個實例最大連接數
server 192.168.1.11:8080 max_conns=100;
# 使用最少連接策略分散負載
least_conn;
}

5. 健康檢查與故障轉移
問題描述:

  • 殭屍實例繼續接收流量
  • 故障轉移不及時
  • 雪崩效應

解決方案:

upstream backend_servers {
server 192.168.1.10:8080 max_fails=3 fail_timeout=30s;
server 192.168.1.11:8080 max_fails=3 fail_timeout=30s;
# 主動健康檢查(Nginx Plus)
# health_check interval=5s fails=3 passes=2;
}
server {
location / {
proxy_pass http://backend_servers;
# 增強故障轉移配置
proxy_next_upstream error timeout http_500 http_502 http_503 http_504;
proxy_next_upstream_tries 2;
proxy_next_upstream_timeout 10s;
}
}

6. 緩存一致性問題
問題描述:

  • 本地緩存不一致
  • 緩存失效策略難以同步

解決方案:

# 使用分佈式緩存
upstream backend_servers {
server 192.168.1.10:8080;
server 192.168.1.11:8080;
}
# 在Nginx層面添加統一緩存
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m;
server {
location / {
proxy_pass http://backend_servers;
proxy_cache my_cache;
proxy_cache_valid 200 302 10m;
}
}

7. 日誌收集與監控困難

問題描述:

  • 日誌分散在不同實例
  • 問題排查困難
  • 性能監控不全面

解決方案:

# 統一的日誌格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'upstream: $upstream_addr response_time: $upstream_response_time';
access_log /var/log/nginx/access.log main;

8. SSL/TLS終止性能問題

問題描述:

  • SSL加解密消耗CPU資源
  • 影響Nginx性能

解決方案:

# 在Nginx終止SSL,後端使用HTTP
server {
listen 443 ssl;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location / {
proxy_pass http://backend_servers;  # 注意是http://
}
}

完整的解決方案:

http {
# 分佈式會話存儲
upstream redis_cluster {
server 192.168.1.50:6379;
server 192.168.1.51:6379;
}
# 應用集羣
upstream app_cluster {
least_conn;
server 192.168.1.10:8080 max_fails=3 fail_timeout=30s;
server 192.168.1.11:8080 max_fails=3 fail_timeout=30s;
keepalive 32;
}
server {
listen 80;
# 靜態資源直接由Nginx處理
location /static/ {
alias /shared_storage/static/;
expires 1y;
add_header Cache-Control "public, immutable";
}
# API請求負載均衡
location /api/ {
proxy_pass http://app_cluster;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 故障轉移配置
proxy_next_upstream error timeout http_500 http_502 http_503 http_504;
}
# 健康檢查端點
location /health {
access_log off;
proxy_pass http://app_cluster/health;
}
}
}

希望這份指南能幫助你順利配置 Nginx 負載均衡。如果你能分享一下你計劃使用負載均衡的具體業務場景,或許我能給你提供更具體的算法選型建議。