背景與問題
Nginx 是高性能 HTTP 服務(wù)器和反向代理服務(wù)器,默認(rèn)配置適合低流量場(chǎng)景。當(dāng) QPS(每秒請(qǐng)求數(shù))達(dá)到數(shù)千甚至數(shù)萬時(shí),默認(rèn)配置會(huì)成為性能瓶頸。表現(xiàn)為:服務(wù)器 CPU 使用率不高但請(qǐng)求開始排隊(duì)、響應(yīng)時(shí)間隨并發(fā)增加急劇上升、連接數(shù)達(dá)到上限后開始拒絕服務(wù)。
本文以 Nginx 1.27.x 版本為基準(zhǔn),系統(tǒng)講解高并發(fā)場(chǎng)景下必須調(diào)整的核心參數(shù),以及每個(gè)參數(shù)調(diào)整背后的原理。內(nèi)容包括:工作進(jìn)程配置、連接管理、緩沖區(qū)優(yōu)化、緩存策略、 upstream 負(fù)載均衡調(diào)優(yōu)、HTTP 協(xié)議優(yōu)化、以及內(nèi)核參數(shù)調(diào)整。文章覆蓋的參數(shù)都經(jīng)過生產(chǎn)環(huán)境驗(yàn)證,調(diào)整思路按優(yōu)先級(jí)排序,讀者可以根據(jù)實(shí)際場(chǎng)景按圖索驥。
1. 參數(shù)調(diào)整總覽與優(yōu)先級(jí)
Nginx 參數(shù)調(diào)整有明確的優(yōu)先級(jí)順序。錯(cuò)誤地調(diào)整低優(yōu)先級(jí)參數(shù)可能無效,而正確地調(diào)整高優(yōu)先級(jí)參數(shù)能立即見效。優(yōu)先級(jí)從高到低:
第一層是操作系統(tǒng)內(nèi)核參數(shù),影響 Nginx 能處理的最大連接數(shù)和文件描述符上限。第二層是 Nginx 進(jìn)程模型配置,即 worker 進(jìn)程數(shù)和連接處理方式。第三層是每個(gè)連接的內(nèi)存緩沖區(qū)配置。第四層是 upstream 負(fù)載均衡和 keepalive 配置。第五層是 HTTP 協(xié)議層面的優(yōu)化,如 gzip、chunked 編碼等。
按這個(gè)順序逐層調(diào)整,每調(diào)整一層后觀察效果,避免盲目修改。
2. 內(nèi)核參數(shù)調(diào)整
2.1 文件描述符上限
Nginx 每個(gè)連接需要占用一個(gè)文件描述符(FD),同時(shí)還需要額外的文件描述符用于打開日志文件、連接 upstream、打開緩存文件等。默認(rèn)系統(tǒng)限制通常為 1024,遠(yuǎn)不夠高并發(fā)使用。
檢查當(dāng)前限制:
# 查看系統(tǒng)級(jí)別的最大文件描述符 cat /proc/sys/fs/file-max # 查看當(dāng)前已使用的文件描述符數(shù)量 cat /proc/sys/fs/file-nr # 查看 nginx 進(jìn)程允許的最大 FD(soft limit) cat /proc/$(cat /var/run/nginx.pid)/limits | grep"Max open files"
調(diào)整系統(tǒng)級(jí)限制:
# 在 /etc/sysctl.conf 中添加 fs.file-max = 1000000 # 使配置生效 sysctl -p
調(diào)整用戶級(jí)限制(在/etc/security/limits.conf中):
nginx soft nofile 100000 nginx hard nofile 100000
在 Nginx 配置中設(shè)置:
worker_rlimit_nofile 100000;
這個(gè)參數(shù)設(shè)置了 Nginx worker 進(jìn)程能打開的最大文件描述符數(shù)量。應(yīng)設(shè)置為與用戶級(jí)限制一致。計(jì)算公式:理論最大連接數(shù) = worker_rlimit_nofile / 2(因?yàn)槊總€(gè)連接需要 1 個(gè) FD,還要留一些給日志、upstream、緩存等)。
2.2 網(wǎng)絡(luò)內(nèi)核參數(shù)
高并發(fā)場(chǎng)景下,網(wǎng)絡(luò)積壓隊(duì)列和連接復(fù)用相關(guān)的內(nèi)核參數(shù)必須調(diào)整:
# 在 /etc/sysctl.conf 中添加 # 調(diào)整 SOMAXCONN(Socket 監(jiān)聽隊(duì)列最大長(zhǎng)度) net.core.somaxconn = 65535 # 調(diào)整 tcp 連接隊(duì)列大小 net.ipv4.tcp_max_syn_backlog = 65535 # 允許 TIME_WAIT 狀態(tài)的 socket 重用 net.ipv4.tcp_tw_reuse = 1 # 調(diào)整 TIME_WAIT 超時(shí)時(shí)間(毫秒) net.ipv4.tcp_fin_timeout = 15000 # 調(diào)整 TCP keepalive 探測(cè)間隔 net.ipv4.tcp_keepalive_time = 600 net.ipv4.tcp_keepalive_intvl = 30 net.ipv4.tcp_keepalive_probes = 3 # 調(diào)整本地端口范圍 net.ipv4.ip_local_port_range = 1024 65535 # 調(diào)整 tcp 最大包緩沖大小 net.core.rmem_max = 16777216 net.core.wmem_max = 16777216 net.core.rmem_default = 262144 net.core.wmem_default = 262144 net.ipv4.tcp_rmem = 4096 87380 16777216 net.ipv4.tcp_wmem = 4096 65536 16777216
使配置生效:sysctl -p
參數(shù)原理解析:
net.core.somaxconn是 listen() 系統(tǒng)調(diào)用的 backlog 隊(duì)列長(zhǎng)度。當(dāng) Nginx 調(diào)用 listen() 時(shí),內(nèi)核會(huì)將未 accept 的連接放入這個(gè)隊(duì)列。如果隊(duì)列滿了,新連接會(huì)被拒絕。Nginx 默認(rèn)的 backlog 為 511,如果上游處理速度跟不上連接到達(dá)速度,這個(gè)隊(duì)列會(huì)很快填滿。
net.ipv4.tcp_max_syn_backlog是 SYN 隊(duì)列的長(zhǎng)度。當(dāng)客戶端發(fā)送 SYN 包后,服務(wù)器回復(fù) SYN-ACK 但還未收到最后的 ACK 時(shí),連接處于半開狀態(tài),放在 SYN 隊(duì)列中。如果 SYN 隊(duì)列滿了,新的 SYN 包會(huì)被丟棄,導(dǎo)致連接建立失敗。
net.ipv4.tcp_tw_reuse允許將 TIME_WAIT 狀態(tài)的 socket 重用于新的 outbound 連接。這在 Nginx 作為客戶端連接 upstream 時(shí)特別有用,減少本地端口耗盡的問題。
net.ipv4.tcp_fin_timeout縮短 TIME_WAIT 持續(xù)時(shí)間。默認(rèn) 60 秒,在高并發(fā)場(chǎng)景下會(huì)占用大量端口資源。
3. Nginx 進(jìn)程模型配置
3.1 worker 進(jìn)程數(shù)
Nginx 采用多進(jìn)程模型:一個(gè) master 進(jìn)程負(fù)責(zé)管理,多個(gè) worker 進(jìn)程處理請(qǐng)求。默認(rèn)配置只有一個(gè) worker 進(jìn)程,遠(yuǎn)不能利用多核 CPU。
檢查 CPU 核心數(shù):
nproc # 或者 grep processor /proc/cpuinfo | wc -l
設(shè)置 worker 進(jìn)程數(shù):
worker_processes auto;
auto表示 Nginx 自動(dòng)設(shè)置為 CPU 核心數(shù),這是最推薦的配置。如果設(shè)置為具體數(shù)字,必須確保與 CPU 核心數(shù)匹配。worker 進(jìn)程數(shù)不是越多越好:進(jìn)程數(shù)過多會(huì)增加進(jìn)程切換開銷,每個(gè)進(jìn)程還要占用獨(dú)立內(nèi)存。
3.2 worker 連接數(shù)上限
每個(gè) worker 進(jìn)程能處理的連接數(shù)受 worker_connections 限制。這個(gè)參數(shù)定義了單個(gè) worker 能同時(shí)持有的最大連接數(shù):
events {
worker_connections 65535;
use epoll;
multi_accept on;
}
use epoll:Linux 下使用 epoll 事件模型,這是最高效的 I/O 多路復(fù)用機(jī)制。FreeBSD 下使用 kqueue,Windows 下使用 select。
multi_accept on:允許一個(gè) worker 進(jìn)程同時(shí)接受多個(gè)新連接。默認(rèn) off 意味著一次只 accept 一個(gè)連接。如果流量集中到達(dá),未 accept 的連接會(huì)排隊(duì)等待。
worker_connections 65535是理論上限,實(shí)際設(shè)置需要結(jié)合worker_rlimit_nofile的值。計(jì)算方式:worker_connections * worker_processes不能超過worker_rlimit_nofile。
3.3 綁定 worker 到特定 CPU
將 worker 進(jìn)程綁定到特定 CPU 核心,可以避免進(jìn)程切換帶來的緩存失效:
worker_cpu_affinity auto;
auto會(huì)自動(dòng)將每個(gè) worker 綁定到不同的 CPU 核心。如果需要手動(dòng)指定:
worker_cpu_affinity 0001 0010 0100 1000; # 4 worker 對(duì)應(yīng) 4 核心 worker_cpu_affinity 0101 1010; # 2 worker 對(duì)應(yīng) 4 核心(每進(jìn)程綁定2個(gè))
手動(dòng)指定在 NUMA 架構(gòu)服務(wù)器上特別有用,可以控制每個(gè) worker 只訪問本地內(nèi)存,減少跨 NUMA 節(jié)點(diǎn)的內(nèi)存訪問延遲。
3.4 調(diào)整 worker 優(yōu)先級(jí)
如果服務(wù)器上還運(yùn)行著其他重要服務(wù),可以適當(dāng)降低 Nginx worker 的優(yōu)先級(jí),避免 Nginx 搶光 CPU:
worker_priority -10;
負(fù)數(shù)表示更高優(yōu)先級(jí)(Linux 中 Nice 值)。默認(rèn) 0,降低到 -10 可以讓 Nginx 在爭(zhēng)搶時(shí)獲得更多 CPU 時(shí)間。但如果服務(wù)器專門跑 Nginx,不需要調(diào)整。
4. 緩沖區(qū)配置
4.1 客戶端連接緩沖區(qū)
客戶端請(qǐng)求的headers和body需要緩沖區(qū)來存儲(chǔ)。緩沖區(qū)太小會(huì)導(dǎo)致 nginx 頻繁讀寫磁盤,太大會(huì)占用過多內(nèi)存:
http {
# client header buffer size
client_header_buffer_size 4k;
large_client_header_buffers 4 32k;
# client body buffer size(上傳文件大小控制)
client_body_buffer_size 128k;
# 最大允許的 request body 大?。ㄔ?server/location 中設(shè)置)
client_max_body_size 100m;
}
client_header_buffer_size:存儲(chǔ)請(qǐng)求頭的緩沖區(qū)大小。普通請(qǐng)求的 headers 通常小于 1KB,4KB 足夠。如果存在大量 cookies 或較大的 headers,可以增大。
large_client_header_buffers:如果請(qǐng)求頭太大超出 client_header_buffer_size,會(huì)使用這個(gè)緩沖區(qū)。第一個(gè)數(shù)字是緩沖區(qū)數(shù)量,第二個(gè)是每個(gè)緩沖區(qū)大小。如果出現(xiàn)大量 400 Bad Request 錯(cuò)誤且錯(cuò)誤日志顯示 "request header is too large",需要增加這個(gè)值。
client_body_buffer_size:存儲(chǔ)請(qǐng)求 body 的緩沖區(qū)大小。如果 body 超過這個(gè)大小,會(huì)寫入臨時(shí)文件。默認(rèn)是磁盤上的 tmpfs(如果配置了client_body_temp_path)。這個(gè)值設(shè)置得太小會(huì)導(dǎo)致頻繁寫磁盤,設(shè)置得太大會(huì)占用過多內(nèi)存。
4.2 upstream 緩沖區(qū)
upstream 響應(yīng)數(shù)據(jù)也需要緩沖區(qū)。啟用緩沖區(qū)可以讓 Nginx 異步處理 upstream 響應(yīng),減少阻塞:
upstream backend {
server 127.0.0.1:8080;
keepalive 32;
}
proxy_buffer_size 128k;
proxy_buffers 4 128k;
proxy_buffering on;
proxy_busy_buffers_size 256k;
proxy_buffer_size:存儲(chǔ) upstream 響應(yīng)的 headers 部分。這個(gè)值應(yīng)該大于 upstream 可能返回的最大 headers 大小。
proxy_buffers:存儲(chǔ) upstream 響應(yīng)的 body 部分。第一個(gè)數(shù)字是緩沖區(qū)數(shù)量,第二個(gè)是每個(gè)緩沖區(qū)大小。如果 upstream 返回大文件,這個(gè)值需要足夠大。
proxy_buffering on:?jiǎn)⒂庙憫?yīng)緩沖。如果關(guān)閉,Nginx 同步轉(zhuǎn)發(fā) upstream 響應(yīng),會(huì)阻塞 worker 進(jìn)程直到數(shù)據(jù)傳輸完成。對(duì)于靜態(tài)文件和大多數(shù) API 響應(yīng),開啟緩沖是最佳選擇。
proxy_busy_buffers_size:當(dāng)這個(gè)大小的緩沖區(qū)被填滿后,開始向客戶端發(fā)送數(shù)據(jù),同時(shí)繼續(xù)從 upstream 讀取數(shù)據(jù)填充緩沖區(qū)。這個(gè)值應(yīng)該是 proxy_buffers 單個(gè)緩沖區(qū)的 2-3 倍。
4.3 FastCGI 緩沖區(qū)(PHP-FPM 場(chǎng)景)
如果 Nginx 后端是 PHP-FPM,使用 fastcgi 緩沖區(qū)配置:
fastcgi_buffer_size 64k; fastcgi_buffers 4 64k; fastcgi_busy_buffers_size 128k; fastcgi_temp_file_write_size 256k; fastcgi_connect_timeout 60s; fastcgi_send_timeout 60s; fastcgi_read_timeout 60s;
fastcgi_connect_timeout:與 FastCGI 服務(wù)器建立連接的超時(shí)時(shí)間。不建議超過 75 秒。
fastcgi_send_timeout:向 FastCGI 服務(wù)器發(fā)送請(qǐng)求的超時(shí)時(shí)間。不是整個(gè)響應(yīng)傳輸時(shí)間,而是兩次寫操作之間的超時(shí)。
fastcgi_read_timeout:從 FastCGI 服務(wù)器讀取響應(yīng)的超時(shí)時(shí)間。如果 PHP 腳本執(zhí)行時(shí)間很長(zhǎng),需要增大這個(gè)值。
5. 超時(shí)配置
5.1 客戶端超時(shí)
http {
# 客戶端保持連接的超時(shí)(兩次請(qǐng)求之間)
keepalive_timeout 65;
# 客戶端發(fā)送請(qǐng)求頭的超時(shí)
client_header_timeout 15s;
# 客戶端發(fā)送請(qǐng)求體的超時(shí)
client_body_timeout 15s;
# 響應(yīng)發(fā)送超時(shí)(兩次寫操作之間)
send_timeout 30s;
}
keepalive_timeout:HTTP keep-alive 保持連接的時(shí)間。設(shè)置太短會(huì)導(dǎo)致頻繁建立連接增加開銷;設(shè)置太長(zhǎng)會(huì)占用連接資源。65 秒是常見的折中值。
client_header_timeout:客戶端必須在指定時(shí)間內(nèi)發(fā)送完整的請(qǐng)求頭。如果超時(shí),返回 408 Request Timeout。
client_body_timeout:客戶端必須在指定時(shí)間內(nèi)發(fā)送完整的請(qǐng)求體。如果超時(shí),返回 408 Request Timeout。
send_timeout:向客戶端發(fā)送響應(yīng)時(shí)的超時(shí)。不是整個(gè)響應(yīng)發(fā)送完成的時(shí)間,而是兩次 write 操作之間的超時(shí)。如果客戶端接收數(shù)據(jù)慢,Nginx 會(huì)在這個(gè)時(shí)間后關(guān)閉連接。
5.2 upstream 超時(shí)
upstream backend {
server 127.0.0.1:8080;
keepalive 32;
keepalive_requests 1000;
keepalive_timeout 60s;
}
keepalive:連接池中保持的空閑連接數(shù)量。這個(gè)數(shù)量不是越大越好:每個(gè)連接占用文件描述符和內(nèi)存,過多會(huì)造成資源浪費(fèi)。通常設(shè)置為 expected concurrent requests / worker_processes。
keepalive_requests:一個(gè) keepalive 連接最多處理的請(qǐng)求數(shù)。處理完指定數(shù)量后,連接會(huì)被關(guān)閉并重新建立,防止內(nèi)存泄漏。
keepalive_timeout:keepalive 連接保持空閑的超時(shí)時(shí)間。
6. 壓縮與傳輸優(yōu)化
6.1 Gzip 壓縮
啟用 gzip 壓縮可以大幅減少傳輸數(shù)據(jù)量,提升響應(yīng)速度:
http {
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_proxied any;
gzip_comp_level 4;
gzip_types text/plain text/css text/xml application/json application/javascript application/xml application/xml+rss;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_disable "MSIE [1-6].";
}
gzip on:?jiǎn)⒂?gzip 壓縮。
gzip_vary on:在響應(yīng)頭中添加Vary: Accept-Encoding,告訴緩存服務(wù)器根據(jù) Accept-Encoding 緩存不同版本。
gzip_min_length 1024:小于 1024 字節(jié)的響應(yīng)不壓縮。壓縮小文件的壓縮率低且消耗 CPU,不值得。
gzip_proxied any:代理請(qǐng)求也啟用壓縮,不管請(qǐng)求頭是什么。
gzip_comp_level 4:壓縮級(jí)別 1-9。級(jí)別越高壓縮率越高,但 CPU 開銷也越大。4 是平衡點(diǎn),大多數(shù)場(chǎng)景下最優(yōu)。
gzip_types:指定要壓縮的 MIME 類型。不在列表中的內(nèi)容不會(huì)被壓縮。
**gzip_disable "MSIE [1-6]."**:禁止 IE6 對(duì) gzip 內(nèi)容的處理(IE6 對(duì) gzip 支持有 bug)。
6.2 靜態(tài)資源緩存
對(duì)于不常變化的靜態(tài)資源,設(shè)置長(zhǎng)期緩存減少重復(fù)請(qǐng)求:
location ~* .(jpg|jpeg|png|gif|ico|css|js|woff|woff2|ttf|eot)$ { expires 30d; add_header Cache-Control "public, no-transform"; access_log off; }
expires 30d:設(shè)置緩存時(shí)間為 30 天。靜態(tài)資源應(yīng)該設(shè)置較長(zhǎng)的緩存時(shí)間。
**add_header Cache-Control "public, no-transform"`**:添加緩存控制頭。public 表示任何緩存都可以存儲(chǔ);no-transform 表示不允許轉(zhuǎn)換內(nèi)容(如禁止 CDN 重新壓縮圖片)。
access_log off:關(guān)閉靜態(tài)資源的日志記錄,減少無效日志。
6.3 Sendfile 零拷貝
Linux 的 sendfile 系統(tǒng)調(diào)用可以減少內(nèi)核態(tài)與用戶態(tài)之間的數(shù)據(jù)拷貝:
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
}
sendfile on:?jiǎn)⒂?sendfile 系統(tǒng)調(diào)用。這是 Linux 高效傳輸文件的標(biāo)準(zhǔn)方式,避免了內(nèi)核緩沖區(qū)到用戶緩沖區(qū)再到網(wǎng)絡(luò)緩沖區(qū)的多次拷貝。
tcp_nopush on:在 Linux 上啟用。與 sendfile 配合使用,當(dāng)發(fā)送 HTTP 響應(yīng)頭時(shí),先不發(fā)送數(shù)據(jù)包,而是積累數(shù)據(jù)然后一次性發(fā)送。這減少了網(wǎng)絡(luò)小包的數(shù)量。
tcp_nodelay on:禁用 Nagle 算法。對(duì)于實(shí)時(shí)性要求高的應(yīng)用(如 SSH、游戲),應(yīng)該啟用;對(duì)于 HTTP 服務(wù),兩個(gè)都應(yīng)該啟用。
7. 連接處理優(yōu)化
7.1 HTTP/2 配置
HTTP/2 相比 HTTP/1.1 有顯著的性能優(yōu)勢(shì):多路復(fù)用減少了連接數(shù),頭部壓縮減少了傳輸量,服務(wù)器推送可以主動(dòng)發(fā)送資源:
http {
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'TLS_AES_256_GCM_SHA384TLS_AES_128_GCM_SHA256';
ssl_prefer_server_ciphers on;
ssl_session_cache shared10m;
ssl_session_timeout 1d;
}
server {
listen 443 ssl http2;
server_name example.com;
}
listen 443 ssl http2:?jiǎn)⒂?HTTP/2。Nginx 1.27 版本已經(jīng)完整支持 HTTP/2。
ssl_session_cache:SSL session 緩存,減少 SSL 握手開銷。10MB 可以緩存約 40000 個(gè) session。
ssl_session_timeout:SSL session 緩存有效期。
ssl_prefer_server_ciphers on:使用服務(wù)器端配置的加密套件優(yōu)先級(jí),而不是客戶端的偏好。這確保了使用最安全的配置。
7.2 upstream keepalive 配置
Nginx 與 upstream 之間的連接復(fù)用是提升性能的關(guān)鍵:
upstream backend {
server 127.0.0.1:8080;
keepalive 64;
keepalive_requests 10000;
keepalive_timeout 60s;
}
location / {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
proxy_http_version 1.1:HTTP/1.1 才支持 keep-alive。
**proxy_set_header Connection ""**:清除 Connection 頭,避免傳遞 close 指令導(dǎo)致連接被關(guān)閉。設(shè)置空字符串表示使用持久連接。
keepalive 64:每個(gè) upstream server 保持 64 個(gè)空閑連接。如果有 4 個(gè) upstream 進(jìn)程,則總共有 256 個(gè)持久連接。
keepalive_requests 10000:每個(gè)連接處理 10000 個(gè)請(qǐng)求后關(guān)閉,防止內(nèi)存泄漏。
7.3 連接隊(duì)列與限流
在高并發(fā)場(chǎng)景下,需要限制最大并發(fā)數(shù)防止壓垮 upstream:
limit_req_zone $binary_remote_addr zone=req_limit:10m rate=1000r/s;
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
server {
location / {
# 限流:每秒 1000 個(gè)請(qǐng)求
limit_req zone=req_limit burst=2000 nodelay;
# 連接數(shù)限制:每個(gè) IP 最多 100 個(gè)并發(fā)連接
limit_conn conn_limit 100;
proxy_pass http://backend;
}
}
limit_req_zone:定義限流規(guī)則。$binary_remote_addr 是客戶端 IP 的二進(jìn)制形式,比字符串形式更省內(nèi)存。
rate=1000r/s:每秒鐘 1000 個(gè)請(qǐng)求。burst=2000 表示允許突發(fā)到 2000 個(gè)請(qǐng)求。nodelay 表示突發(fā)請(qǐng)求不延遲處理。
limit_conn:限制單個(gè)客戶端的并發(fā)連接數(shù)。超過后返回 503 Service Unavailable。
8. 緩存配置
8.1 代理緩存
Nginx 可以緩存 upstream 響應(yīng),減少對(duì)后端服務(wù)器的請(qǐng)求:
proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=api_cache:100m max_size=10g inactive=60m use_temp_path=off;
server {
location /api/ {
proxy_pass http://backend;
proxy_cache api_cache;
proxy_cache_valid 200 60s;
proxy_cache_valid 404 10s;
proxy_cache_use_stale error timeout updating;
add_header X-Cache-Status $upstream_cache_status;
}
}
proxy_cache_path:定義緩存存儲(chǔ)路徑和參數(shù)。
levels=1:2:緩存鍵的目錄層級(jí)
keys_zone=api_cache:100m:共享內(nèi)存區(qū)名稱和大小,100m 可以緩存約 100 萬個(gè) key
max_size=10g:緩存最大磁盤占用
inactive=60m:60 分鐘內(nèi)未被訪問的緩存自動(dòng)清除
use_temp_path=off:緩存直接寫入最終路徑,不經(jīng)過臨時(shí)目錄,減少文件移動(dòng)
proxy_cache_valid:不同狀態(tài)碼的緩存有效期。200 響應(yīng)緩存 60 秒,404 緩存 10 秒。
proxy_cache_use_stale:當(dāng) upstream 發(fā)生錯(cuò)誤或超時(shí)時(shí),使用舊的緩存響應(yīng)。這提升了用戶體驗(yàn),但需要業(yè)務(wù)上接受返回舊數(shù)據(jù)的風(fēng)險(xiǎn)。
$upstream_cache_status:顯示緩存命中狀態(tài),值為 HIT/MISS/EXPIRED/UPDATING/BYPASS/STALE。這個(gè) header 幫助前端判斷數(shù)據(jù)是否來自緩存。
8.2 緩存清理
當(dāng) upstream 數(shù)據(jù)更新時(shí),需要主動(dòng)清理緩存:
# 需要加載 ngx_cache_purge 模塊
location ~ /purge(/.*) {
proxy_cache_purge api_cache $1;
}
使用方式:curl -X PURGE http://example.com/purge/api/users/123
這會(huì)在數(shù)據(jù)更新后主動(dòng)清除緩存,確保用戶立即獲取最新數(shù)據(jù)。
9. 負(fù)載均衡策略選擇
9.1 輪詢與加權(quán)輪詢
默認(rèn)的負(fù)載均衡策略是輪詢,每個(gè) upstream 依次處理請(qǐng)求:
upstream backend {
server 127.0.0.1:8080 weight=5;
server 127.0.0.1:8081 weight=3;
server 127.0.0.1:8082 weight=2;
}
加權(quán)輪詢用于 upstream 性能不一致的場(chǎng)景。weight 越大的 server 分到的請(qǐng)求越多。性能好的機(jī)器 weight 設(shè)置更高。
9.2 最少連接數(shù)
最少連接數(shù)策略將請(qǐng)求發(fā)送到當(dāng)前連接數(shù)最少的 upstream:
upstream backend {
least_conn;
server 127.0.0.1:8080;
server 127.0.0.1:8081;
}
適合請(qǐng)求處理時(shí)間差異較大的場(chǎng)景。長(zhǎng)時(shí)間占用連接的請(qǐng)求不會(huì)讓某臺(tái) upstream 過載。
9.3 IP 哈希
IP 哈希策略保證來自同一 IP 的請(qǐng)求始終打到同一臺(tái) upstream:
upstream backend {
ip_hash;
server 127.0.0.1:8080;
server 127.0.0.1:8081;
server 127.0.0.1:8082;
}
適合需要會(huì)話保持的場(chǎng)景。但當(dāng)某臺(tái) upstream 下線時(shí),可能導(dǎo)致會(huì)話丟失(除非使用 ip_hash 配合 down)。
9.4 最少響應(yīng)時(shí)間
Nginx Plus(商業(yè)版)支持最少響應(yīng)時(shí)間策略,將請(qǐng)求發(fā)送到平均響應(yīng)時(shí)間最短的 upstream。開源版可以通過第三方模塊如 nginx-upsync-module 或 Consul 配合實(shí)現(xiàn)動(dòng)態(tài)負(fù)載均衡。
10. 高可用與容災(zāi)
10.1 upstream 健康檢查
Nginx 開源版沒有內(nèi)置健康檢查,需要通過配置實(shí)現(xiàn)被動(dòng)健康檢查:
upstream backend {
server 127.0.0.1:8080 max_fails=3 fail_timeout=30s;
server 127.0.0.1:8081 max_fails=3 fail_timeout=30s;
server 127.0.0.1:8082 max_fails=3 fail_timeout=30s;
}
max_fails=3:連續(xù) 3 次失敗后,認(rèn)為該 server 不可用。
fail_timeout=30s:不可用狀態(tài)持續(xù) 30 秒后,重新嘗試該 server。
這種被動(dòng)檢查依賴真實(shí)請(qǐng)求來判斷 server 健康狀態(tài)。如果某臺(tái) upstream 掛了,在排查完成前會(huì)有少量失敗請(qǐng)求。
10.2 backup 與 down
upstream backend {
server 127.0.0.1:8080 weight=5;
server 127.0.0.1:8081 weight=3;
server 127.0.0.1:8082 backup; # 備份 server
}
backup:標(biāo)記為備份 server。只有在所有非 backup server 都不可用時(shí),才啟用。
down:標(biāo)記為永久下線,用于臨時(shí)維護(hù)。
10.3 主備架構(gòu)
在雙 Nginx 主備場(chǎng)景中,使用 Keepalived 做 VIP 漂移:
# Nginx Master 配置
virtual_server 192.168.1.100 443 {
delay_loop 6
lb_algo rr
lb_kind VRRP
persistence_timeout 0
protocol TCP
real_server 192.168.1.101 443 {
weight 1
TCP_CHECK {
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
real_server 192.168.1.102 443 {
weight 1
TCP_CHECK {
connect_timeout 3
nb_get_retry 3
delay_before_retry 3
}
}
}
Keepalived 定期探測(cè) real_server 的健康狀態(tài),當(dāng) Master 不可用時(shí),VIP 自動(dòng)漂移到 Backup。這個(gè)架構(gòu)保證 Nginx 層的 HA。
11. 生產(chǎn)環(huán)境驗(yàn)證清單
完成參數(shù)調(diào)整后,必須逐項(xiàng)驗(yàn)證:
Nginx 配置語法正確:nginx -t
文件描述符上限已生效:ulimit -n應(yīng)顯示 100000 或更大
worker 進(jìn)程數(shù)正確:ps aux | grep nginx應(yīng)顯示多個(gè) worker
端口監(jiān)聽正常:ss -tlnp | grep nginx應(yīng)顯示監(jiān)聽端口
upstream 連接池生效:觀察netstat -an | grep ESTABLISHED | grep upstream_port連接數(shù)
限流生效:使用 ab 或 wrk 壓測(cè)驗(yàn)證
緩存生效:檢查 X-Cache-Status 響應(yīng)頭顯示 HIT
性能提升驗(yàn)證:對(duì)比調(diào)整前后的 QPS 和延遲 P99
12. 常見誤區(qū)
12.1 誤區(qū)一:worker_processes 設(shè)置越大越好
實(shí)際:worker_processes 應(yīng)該等于 CPU 核心數(shù)。超過 CPU 核心數(shù)后,進(jìn)程切換開銷反而降低性能。可以用top或htop觀察 CPU 使用率,如果多個(gè) worker 的 CPU 使用率都接近 100% 且總體已無提升空間,說明配置合理。
12.2 誤區(qū)二:worker_connections 設(shè)置為系統(tǒng)最大 FD
實(shí)際:worker_connections * worker_processes 必須小于 worker_rlimit_nofile。因?yàn)槌诉B接,還有日志文件、upstream 連接、緩存文件描述符等占用。通常 worker_connections 設(shè)置為 worker_rlimit_nofile 的 60-70% 較為安全。
12.3 誤區(qū)三:gzip 壓縮級(jí)別越高越好
實(shí)際:gzip 壓縮級(jí)別 1-9,級(jí)別越高壓縮率提升有限但 CPU 開銷指數(shù)增長(zhǎng)。測(cè)試數(shù)據(jù)表明,級(jí)別 1 的壓縮速度是級(jí)別 9 的 5-10 倍,而壓縮率差異通常不超過 10%。建議使用級(jí)別 4 或 5。
12.4 誤區(qū)四:proxy_buffering 永遠(yuǎn)應(yīng)該開啟
實(shí)際:對(duì)于需要實(shí)時(shí)推送數(shù)據(jù)的場(chǎng)景(如長(zhǎng)輪詢、Server-Sent Events),關(guān)閉 proxy_buffering 讓數(shù)據(jù)實(shí)時(shí)轉(zhuǎn)發(fā)更合適。判斷標(biāo)準(zhǔn):如果 upstream 返回的數(shù)據(jù)需要立即到達(dá)客戶端,就關(guān)閉緩沖;如果可以接受一定延遲,就開啟。
13. 總結(jié)
高并發(fā)場(chǎng)景下 Nginx 優(yōu)化的核心是:最大化連接處理能力、最小化每個(gè)請(qǐng)求的開銷、合理利用緩存和壓縮減少數(shù)據(jù)傳輸。
參數(shù)調(diào)整的優(yōu)先級(jí)是:內(nèi)核參數(shù)大于進(jìn)程模型大于緩沖區(qū)配置大于協(xié)議優(yōu)化。按這個(gè)順序逐層調(diào)整,每層調(diào)整后觀察效果。
優(yōu)化不是一勞永逸。流量模式變化、upstream 性能變化、業(yè)務(wù)邏輯調(diào)整都可能讓原有的最優(yōu)配置不再最優(yōu)。建議建立定期 review 機(jī)制,結(jié)合監(jiān)控?cái)?shù)據(jù)分析配置是否仍然合理。
最終,所有優(yōu)化都應(yīng)該回歸到業(yè)務(wù)指標(biāo):QPS、延遲 P99/P95、錯(cuò)誤率。只有這些指標(biāo)改善了,優(yōu)化才是有效的。
-
cpu
+關(guān)注
關(guān)注
68文章
11326瀏覽量
225845 -
服務(wù)器
+關(guān)注
關(guān)注
14文章
10347瀏覽量
91740 -
nginx
+關(guān)注
關(guān)注
0文章
194瀏覽量
13206
原文標(biāo)題:高并發(fā)場(chǎng)景下,Nginx 性能優(yōu)化應(yīng)該先改哪些參數(shù)?
文章出處:【微信號(hào):magedu-Linux,微信公眾號(hào):馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
Linux上Nginx獲得最佳性能的8種方法
Linux運(yùn)維Nginx軟件優(yōu)化之安全優(yōu)化
Linux運(yùn)維Nginx軟件優(yōu)化之Nginx性能優(yōu)化
Linux運(yùn)維Nginx軟件優(yōu)化之日志優(yōu)化
主要學(xué)習(xí)下nginx的安裝配置
介紹 Nginx的基本概念,性能,SSL 安裝
Nginx的詳細(xì)知識(shí)點(diǎn)講解
高性能Nginx HTTPS調(diào)優(yōu)-如何為HTTPS提速30%
如何通過Nginx實(shí)現(xiàn)遠(yuǎn)程調(diào)試本機(jī)代碼
Nginx 如何實(shí)現(xiàn)高性能低消耗
Nginx性能優(yōu)化終極指南
Nginx性能優(yōu)化應(yīng)該先改哪些參數(shù)
評(píng)論