開始使用nginx的實戰負載平衡指南
許多開發者只把nginx當作「反向代理 + 靜態文件服務」使用,但實際上nginx是一個相當強大的軟體負載平衡器。如果你是同時管理伺服器的開發者,僅靠熟練使用nginx,就能在流量高峰時顯著提升服務的穩定性與效能。
本文針對初學者到中級開發者,一次性整理以下內容:
- 負載平衡概念
- nginx負載平衡設定方法
- 演算法(round robin、least_conn、ip_hash 等)
- 健康檢查(Health Check)
- 常用選項
1. 什麼是負載平衡?
負載平衡(load balancing)簡單來說,就是:
「將請求平均分配到多台伺服器,避免單台過載」
為什麼需要?
- 防止流量暴增 * 即使在高峰時段,單台伺服器也不會因為請求過多而宕機。
- 擴展性(Scale Out) * 透過水平擴充(多台伺服器)提升處理量,而非單台升級硬體。
- 容錯(高可用) * 即使一台伺服器失效,流量仍可轉發到其他伺服器,服務持續運作。
nginx 在負載平衡中的角色
典型架構如下:
客戶端 → nginx(負載平衡器 / 反向代理) → 多台應用伺服器
nginx 接收請求後,將其轉發到後端的某台應用伺服器。
2. 理解 nginx 負載平衡的基本結構
在 nginx 設定中,負載平衡主要分為兩個部分:
- upstream 區塊: * 定義「後端伺服器池」
- server / location 區塊: * 指定進來的請求應該轉發到哪個 upstream
先看最簡單的範例。
http {
upstream app_backend {
server 10.0.0.101:3000;
server 10.0.0.102:3000;
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://app_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;
}
}
}
這個設定的意義
upstream app_backend:將10.0.0.101:3000與10.0.0.102:3000兩台伺服器視為同一個「池」proxy_pass http://app_backend;:將客戶端請求轉發到app_backend池中的某台伺服器- 若未指定演算法,預設使用 round robin(輪詢)
3. 負載平衡演算法種類
nginx 提供多種分配策略,根據實際情況選擇最合適的演算法。
3.1 基本:Round Robin(輪詢)
設定:不寫任何指令即為預設
upstream app_backend {
server 10.0.0.101:3000;
server 10.0.0.102:3000;
}
- 第一個請求 → 伺服器1
- 第二個請求 → 伺服器2
- 第三個請求 → 再回到伺服器1 …
優點:簡單,適用於大多數情況 缺點:不考慮各伺服器目前的負載
3.2 least_conn(最少連線)
upstream app_backend {
least_conn;
server 10.0.0.101:3000;
server 10.0.0.102:3000;
}
- 將新請求送到「目前連線數最少」的伺服器
- 適用於請求處理時間差異較大的服務(例如某些 API 請求耗時較長)
建議使用情境
- 某些請求耗時長,其他請求短
- 伺服器規格相近,但請求模式不均勻
3.3 ip_hash(相同 IP 同一台伺服器)
upstream app_backend {
ip_hash;
server 10.0.0.101:3000;
server 10.0.0.102:3000;
}
- 以客戶端 IP 做哈希,始終將同一 IP 的請求導向同一台伺服器
- 適合需要「粘性 Session」的舊式應用(將 Session 存於伺服器記憶體)
優點:同一使用者請求始終到同一台伺服器 缺點:新增/移除伺服器時,哈希可能改變,導致大量使用者重新映射;若使用代理(Cloudflare、ELB 等)無法取得真實 IP,則無效
3.4 基於權重(weight)的分配
當伺服器規格不同,想將更多流量分配給性能較好的伺服器時可使用。
upstream app_backend {
server 10.0.0.101:3000 weight=3;
server 10.0.0.102:3000 weight=1;
}
- 伺服器1 : 伺服器2 = 3 : 1 的比例分配
- 適合新加入的高規格伺服器先行使用
4. 健康檢查(Health Check)與失效伺服器處理
為了讓負載平衡器真正「聰明」,必須能自動將失效伺服器剔除。
nginx 開源版預設支援 被動健康檢查(passive health check)。
4.1 max_fails / fail_timeout
upstream app_backend {
server 10.0.0.101:3000 max_fails=3 fail_timeout=30s;
server 10.0.0.102:3000 max_fails=3 fail_timeout=30s;
}
max_fails=3:連續三次失敗即視為「異常」fail_timeout=30s:在 30 秒內不再將流量送往該伺服器;之後若再次成功則重新使用
「失敗」通常指 502/503/504 回應、連線失敗等。
4.2 proxy_next_upstream
可設定在何種情況下將請求轉發到下一台伺服器。
location / {
proxy_pass http://app_backend;
proxy_next_upstream error timeout http_502 http_503 http_504;
}
- 指定錯誤發生時重試下一台伺服器
- 過度重試會增加延遲,請僅在必要時使用
5. 實戰範例:簡易 Web 服務負載平衡
假設你有兩台 Node.js 應用伺服器,執行於 3000 端口:
10.0.0.101:300010.0.0.102:3000
5.1 nginx 設定範例
http {
upstream app_backend {
least_conn;
server 10.0.0.101:3000 max_fails=3 fail_timeout=30s;
server 10.0.0.102:3000 max_fails=3 fail_timeout=30s;
}
server {
listen 80;
server_name myservice.com;
# 客戶端 → nginx → Node.js 伺服器
location / {
proxy_pass http://app_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;
proxy_read_timeout 60s;
proxy_connect_timeout 5s;
proxy_send_timeout 10s;
}
}
}
重新載入 nginx 後:
- 所有進入
myservice.com的請求會被轉發到連線數最少的 Node.js 伺服器 - 若某台伺服器連續失敗,將在一段時間內自動排除
6. HTTPS(SSL)終止 + 負載平衡
在生產環境中,HTTPS 已成為標準。nginx 常被用作 SSL 終止(termination) 的節點。
http {
upstream app_backend {
least_conn;
server 10.0.0.101:3000;
server 10.0.0.102:3000;
}
server {
listen 443 ssl;
server_name myservice.com;
ssl_certificate /etc/letsencrypt/live/myservice.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/myservice.com/privkey.pem;
location / {
proxy_pass http://app_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;
}
}
# HTTP → HTTPS 重定向
server {
listen 80;
server_name myservice.com;
return 301 https://$host$request_uri;
}
}
- 客戶端與 nginx 之間使用 HTTPS
- nginx 與後端伺服器之間使用 HTTP(內部網路通常如此)
7. Session 問題:粘性 Session 必須嗎?
舊式應用常將 Session 存於伺服器記憶體,這時「同一使用者必須送到同一台伺服器」的需求很高。
nginx 可用 ip_hash 簡單解決,但現代做法多採用:
- 將 Session 存於 Redis 等外部儲存
- 使用 JWT,讓應用無狀態(stateless)
若能在應用層移除狀態,負載平衡器就只需負責流量分配,維運與擴充更為順暢。
8. 常用調優點
8.1 keepalive 設定
重複使用後端連線可提升效能。
upstream app_backend {
least_conn;
server 10.0.0.101:3000;
server 10.0.0.102:3000;
keepalive 32;
}
server {
location / {
proxy_pass http://app_backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}
keepalive 32;:每個 worker 允許最多 32 個 keepalive 連線- 減少 TCP 連線建立的延遲與 CPU 負擔
8.2 緩衝區 & 時間設定
對於大型回應或後端較慢的情況,緩衝與時間設定同樣重要。
location / {
proxy_pass http://app_backend;
proxy_buffering on;
proxy_buffers 16 16k;
proxy_busy_buffers_size 64k;
proxy_read_timeout 60s;
proxy_send_timeout 60s;
}
proxy_read_timeout設得太短會導致 504 Gateway Timeout- 依實際流量與後端效能調整
9. nginx 負載平衡導入策略(分階段)
若服務已運行且集中於單台伺服器,建議按以下步驟逐步擴充。
- 第一階段:先將 nginx 作為反向代理 * 客戶端 → nginx → 現有單台應用伺服器 * 同時啟用 SSL 終止、靜態檔案服務、快取等功能
- 第二階段:複製應用伺服器並配置 upstream
* 複製現有伺服器或新增新伺服器,確保資料同步
* 在
upstream中加入兩台伺服器,開始負載平衡 - 第三階段:健康檢查 + 監控
* 設定
max_fails、fail_timeout、proxy_next_upstream* 引入日誌/指標收集(如 Prometheus + Grafana、ELK 等) - 第四階段:演算法與細部調優
* 根據流量模式選擇
least_conn或weight* 調整 keepalive、緩衝、時間等參數
結語
nginx 不僅僅是「反向代理」;其負載平衡功能非常完善。只要掌握以下幾點:
- 用
upstream定義伺服器池 - 選擇合適的負載平衡演算法(round robin / least_conn / ip_hash / weight)
- 配置健康檢查與重試策略,確保失效伺服器自動剔除
- 在生產環境中使用 HTTPS 終止,保持內部通訊簡單
理解並實踐上述內容後,當你面臨「流量增長,單台伺服器是否足夠?」的疑問時,就能自信地使用 nginx 建立更穩定、更高效的基礎設施。

目前沒有評論。