Nginx 效能調校:HTTP 處理與設定

12 分鐘閱讀 - 2026年5月26日

hero section cover
目錄
  • Nginx HTTP 處理流程:設定調校
  • Nginx 如何處理 HTTP 請求
  • 工作程序與連線
  • 超時與保持連線
  • 緩衝區大小
  • 負載平衡與上游保持活結連
  • 測試與監控
分享

調整 Nginx 工作流程、緩衝區、keepalive 及負載平衡,以在單一伺服器上每秒處理 50,000 個以上的請求。

Nginx HTTP 處理流程:設定調校

Nginx 的預設設定旨在確保相容性,而非追求效能。透過適當的調校,單一伺服器每秒可處理 50,000 至 80,000 次請求。本指南涵蓋最重要的設定項目:工作程序、連線、保持連線 (keepalive)、緩衝、負載平衡,以及如何透過效能測試驗證您的變更。

Nginx 如何處理 HTTP 請求

Nginx 會分階段處理請求,每個階段都會消耗系統資源。了解此流程有助於您針對性地調整設定。

處理流程始於核心層級。傳入的連線會進入 SYN 和 ACCEPT 佇列,並由 Nginx 工作程序(worker processes)進行擷取。一旦接受連線,工作程序便會從核心緩衝區解析 HTTP 請求。若涉及 TLS 傳輸,此步驟將消耗更多 CPU 資源。

接著,Nginx 會根據 Host 標頭及 IP/埠號組合,將請求與虛擬伺服器進行配對,然後透過前綴或正規表達式比對,將 URI 解析至對應的 location 區塊。

對於動態內容,Nginx 會將請求轉發至後端(FastCGI、代理)。此上游通訊階段極度受益於持久連線。若無上游 keepalive,Nginx 將針對每個請求開啟新的 TCP 連線,從而增加延遲與 CPU 開銷。

proxy_buffering 已啟用,Nginx 會將完整的上游回應讀入記憶體中,再傳送給客戶端。這使工作執行緒得以立即處理新的請求。最後,在輸出傳送階段,啟用 sendfile 可實現零拷貝傳輸,將吞吐量從約 6 Gbps 提升至 30 Gbps。

每個階段都會消耗記憶體緩衝區、檔案描述符及 CPU 週期。以下各節將針對每個瓶頸進行優化。

工作程序與連線

請從 worker_processes auto; 。此設定會將工作程序數量與您的 CPU 核心數相匹配。若使用核心數有限的 VPS,請手動設定數量(例如 worker_processes 2;)。若工作負載對記憶體需求較高,請考慮減少工作程序數量,以避免記憶體超額分配。

啟用 worker_cpu_affinity auto; 以將每個工作程序固定至特定核心。此舉可減少快取未命中與上下文切換。此功能自 Nginx 1.9.10 起提供。

連線限制

worker_connections 指令設定每個工作執行緒可處理的同時連線數。總容量為 worker_processes × worker_connections。預設值 512 或 1,024 對於生產環境而言過低。針對高流量網站,應將每工作程的數值設定為 2,048 或 4,096。

每個連線至少需要一個檔案描述符。在反向代理設定中,每個連線會使用兩個(一個用於客戶端,一個用於上游)。將 worker_rlimit_nofile 的值至少為您 worker_connections 值,並預留餘裕。對於 worker_connections 4096;,請使用 worker_rlimit_nofile 10000; 或更高版本。

在系統層級,請將 fs.file-max 的數值 /etc/sysctl.conf 至至少 500,000,並將 systemd 的 LimitNOFILE=65535.

最後,在 multi_accept on; 至 events 區塊中,使工作程序能一次接受所有待處理的連線,而非逐一處理。

超時與保持連線

客戶端保持連線

keepalive_timeout 指令控制閒置的客戶端連線保持開啟的時間長度。對於高流量伺服器,設定為 30 至 65 秒效果良好。請使用雙參數形式:

keepalive_timeout 65s 60s;

第一個值為伺服器端的超時時間。第二個值則會向客戶端傳送 Keep-Alive: timeout=60 標頭傳送給客戶端。將客戶端值設定得稍低一些,可避免瀏覽器試圖重複使用 Nginx 已關閉的連線所導致的競態條件。

keepalive_requests 指令限制單一連線在關閉前可處理的請求數量。預設值為 1,000(自 1.19.10 版本起從 100 提高)。對於穩定的後端服務,可將此值提高至 10,000 以減少連線頻繁切換。

代理超時

proxy_connect_timeout 設定 Nginx 等待與後端建立連線的時間長度。預設值為 60 秒。若需快速故障轉移,請將其縮短至 5 至 10 秒。

proxy_read_timeout 定義 Nginx 在連續讀取上游資料之間的等待時間。請將此值與後端的執行超時設定保持一致。若 PHP-FPM 的 request_terminate_timeout 為 120 秒,請將 proxy_read_timeout 至少設定為 120 秒,以避免過早觸發 504 錯誤。

proxy_send_timeout 控制連續寫入上游之間的間隔。除非您傳送的是大型請求正文,否則預設的 60 秒通常已足夠。

一般而言, proxy_connect_timeout 應始終是這三者中最短的。

緩衝區大小

client_body_buffer_size 控制 Nginx 在記憶體中保留多少傳入請求正文的內容。預設值 8k 或 16k 可處理簡單的表單提交,但檔案上傳時內容會溢出至磁碟。若處理中小型檔案上傳,請將其增加至 128k。若使用者上傳較大檔案,請將 client_max_body_size 若使用者上傳較大檔案,請將此值從預設的 1M 調高。

proxy_buffer_size 此設定會將回應標頭與主體分開處理。預設值 4k 或 8k 通常足夠,但若應用程式含有大型 Set-Cookie (電子商務中常見)可能會超出此限制,導致 502 錯誤。請測量實際標頭大小:

curl -s -w '%{size_header}' -o /dev/null http://your-upstream-url

並將數值向上取整至最接近的 4k 倍數。

proxy_buffers 設定回應正文的緩衝區數量與大小。預設值(8 個 4k 或 8k 的緩衝區,總計 32k 至 64k)無法容納大型 JSON 回應。請測量您最常見的大型回應,並 curl 並配置足夠的緩衝區,使其能完全載入記憶體中。

代理緩衝行為

proxy_buffering on (預設值),Nginx 會將完整的上游回應讀入記憶體中,然後再傳送給客戶端。這讓後端伺服器能夠立即處理新的請求。

proxy_busy_buffers_size 至少為 proxy_buffer_size 加上一個緩衝區,但不得超過您的總緩衝區池。對於 proxy_buffers 8 16k (總計 128k) 的情況下,請將 proxy_busy_buffers_size 值低於 112k。

對於伺服器發送事件(Server-Sent Events)或長輪詢等即時端點,請透過 proxy_buffering off 在特定位置的區塊中。請針對 /stream/events 路徑上,而非全域套用。

負載平衡與上游保持活結連

預設情況下,Nginx 會為每個代理請求建立新的 TCP 連線。每次握手都會增加 10 至 100 毫秒的延遲,而 TLS 還會再增加 10 至 50 毫秒。上游保持活連線(Upstream Keepalive)會維持一組持久連線,以消除此開銷。

需設定以下三項:

upstream backend {
    server 10.0.1.10:8080;
    server 10.0.1.11:8080;
    keepalive 128;
}
 
server {
    location / {
        proxy_pass http://backend;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
    }
}

keepalive 設定值決定每個工作程序的最大閒置連線數。最佳連線池大小可按以下公式計算: (workers × target concurrency) / upstream nodes.

將上游 keepalive_timeout 設為 60 至 120 秒,以配合後端設定並應對流量尖峰。

負載平衡策略

Nginx 支援多種負載平衡方法。輪詢(預設)會依序分配請求。 least_conn 將請求路由至活躍連線最少的伺服器,此方式適用於請求持續時間不固定的工作負載。 ip_hash 透過將相同的客戶端 IP 路由至相同的後端,提供會話持久性。

當伺服器容量各異時,請使用 weight 參數:

upstream backend {
    least_conn;
    server 10.0.1.10:8080 weight=3;
    server 10.0.1.11:8080;
    server 10.0.1.12:8080 backup;
    keepalive 128;
}

加權伺服器接收三倍的流量。 backup 伺服器僅在所有主要伺服器皆離線時才會啟動。請設定 max_failsfail_timeout 進行被動健康檢查,並使用 max_conns 來限制每個後端服務的同時連線數。

測試與監控

在進行任何變更前,務必先測量基準效能。每次變更後,請重新進行效能測試。每次僅進行一項變更。

在重新載入前,請使用 nginx -t 進行驗證。請從獨立機器執行效能測試,以避免資源爭用。

wrk 是 HTTP 負載測試的標準工具:

wrk -t4 -c200 -d30s http://your-server.com/

追蹤每秒請求數、平均延遲、最大延遲及傳輸速率。Apache Bench 適用於較簡單的測試:

ab -n 50000 -c 40 http://your-server.com/

持續監控

啟用 stub_status 模組,透過 curl http://localhost/nginx_status.

在日誌格式中加入時間變數,以識別延遲發生之處:

  • $request_time 用於總請求持續時間
  • $upstream_connect_time 用於後端連線時間
  • $upstream_response_time 用於後端總處理時間

檢查錯誤日誌以確認是否存在緩衝區問題 journalctl -u nginx --no-pager | grep "temporary file"。若回應需讀寫磁碟,表示您的 proxy_buffers 設定過小。請尋找「開啟檔案過多」的錯誤訊息,這表示 worker_rlimit_nofile 需要增加。

透過緩衝記錄來減少日誌 I/O:

access_log /var/log/nginx/access.log combined buffer=64k flush=5s;

在負載測試期間使用 ss -tn state established dst [backend_ip] 在負載測試中驗證連線是否被重複利用,且未在 TIME_WAIT 狀態中堆積。

若需針對高效能工作負載進行優化的專用伺服器與 VPS 主機服務,請參閱 FDC 伺服器

博客

本周特色

更多文章
為什麼擁有強大且不計費的 VPS 是很重要的?

為什麼擁有強大且不計費的 VPS 是很重要的?

需要可靠的效能和無限的流量?功能強大的非計費 VPS 可提供您所需的速度、擴充性和頻寬,而無需擔心使用限制。

3 分鐘閱讀 - 2025年5月9日

如何在 Linux 上優化儲存空間

15 分鐘閱讀 - 2026年5月22日

更多文章