一、基礎概念與核心特性
1. 什么是 Nginx?它的主要用途有哪些?
答案:
Nginx 是一款高性能的開源 Web 服務器、反向代理服務器及負載均衡器,基于事件驅動的異步非阻塞架構,擅長處理高并發場景。
主要用途:
- 靜態資源服務(HTML/CSS/JS/ 圖片等)
- 反向代理與負載均衡(分發請求到后端服務器集群)
- API 網關(處理動態請求轉發)
- 緩存服務(通過
proxy_cache
或fastcgi_cache
加速動態內容) - 實時消息代理(支持 WebSocket 長連接)
2. Nginx 相比 Apache 的核心優勢是什么?
答案:
對比維度 | Nginx | Apache |
---|---|---|
架構 | 單主進程 + 多 worker 進程(異步非阻塞) | 多進程 / 線程(同步阻塞,如 prefork/worker) |
高并發性能 | 支持數萬并發連接,內存占用低 | 并發能力較低,內存占用高 |
靜態資源處理 | 原生高效,無需插件 | 需要mod_static 等插件 |
動態請求處理 | 需配合 FastCGI/Proxy 轉發給后端 | 可通過模塊(如mod_php )直接處理 |
配置靈活性 | 基于模塊化設計,配置簡潔 | 模塊化豐富但配置較復雜 |
解析:Nginx 的異步非阻塞模型(基于 epoll/kqueue)避免了多線程 / 進程的上下文切換開銷,適合高并發、低延遲場景;Apache 則在需要復雜模塊(如 PHP 解析)時更便捷。
3. 解釋 Nginx 的 Master-Worker 進程模型及其作用
答案:
- Master 進程:
- 讀取并驗證配置文件(
nginx.conf
) - 管理 Worker 進程(啟動 / 停止 / 重啟 / 平滑升級)
- 監聽端口,將請求分發到 Worker 進程
- 讀取并驗證配置文件(
- Worker 進程:
- 實際處理客戶端請求,單進程支持數千并發連接
- 通過
worker_connections
控制單個進程最大連接數 - 多 Worker 進程間通過負載均衡(如輪詢)處理請求
優勢:Master 負責管理,Worker 專注處理請求,實現資源隔離與高效并發。
4. 什么是反向代理?反向代理與正向代理的區別?
答案:
- 反向代理:位于服務器端,代理后端集群接收客戶端請求,隱藏真實服務器地址。例如 Nginx 接收請求后轉發到 Tomcat/Node.js 服務器。
- 正向代理:位于客戶端側,代理客戶端向目標服務器發送請求(如瀏覽器通過代理訪問外網)。
核心區別: - 反向代理代理的是服務器,客戶端不知道真實后端;正向代理代理的是客戶端,服務器不知道真實客戶端 IP。
5. 簡述 Nginx 處理 HTTP 請求的流程
答案:
- 客戶端發送請求到 Nginx 監聽端口(如 80/443)。
- Master 進程接收請求,分配給某個 Worker 進程。
- Worker 進程根據
server
塊和location
匹配規則處理請求:- 若為靜態資源,直接讀取文件返回(如
root
/alias
指定路徑)。 - 若為動態請求,通過
proxy_pass
/fastcgi_pass
轉發到后端服務器。
- 若為靜態資源,直接讀取文件返回(如
- 后端服務器處理請求并返回結果,Nginx 將響應返回給客戶端(可能經過緩存、壓縮等處理)。
二、配置與優化
6. 如何配置 Nginx 監聽多個端口?如何指定域名綁定?
答案:
server {listen 80; # 監聽80端口listen 443 ssl; # 監聽443端口并啟用HTTPSserver_name example.com www.example.com; # 綁定域名# 配置HTTPS證書ssl_certificate /path/to/cert.pem;ssl_certificate_key /path/to/key.pem;
}
7. 如何實現 URL 重寫(Rewrite)?舉例說明場景
答案:
使用rewrite
指令結合正則表達式實現重寫,場景如:
- 強制 HTTPS:
server {listen 80;server_name example.com;rewrite ^(.*)$ https://$server_name$1 permanent; # 301重定向 }
- 路徑跳轉:
location /old-path/ {rewrite ^/old-path/(.*)$ /new-path/$1 break; # 內部重寫,不返回客戶端 }
指令說明:permanent
(301)、redirect
(302)、break
(內部跳轉)。
8. 如何配置 Nginx 禁止特定 IP 訪問?
答案:
使用ngx_http_access_module
模塊:
location / {deny 192.168.1.100; # 禁止單個IPdeny 192.168.1.0/24; # 禁止IP段allow all; # 允許其他IP
}
9. 如何優化 Nginx 的靜態資源訪問性能?
答案:
- 開啟
sendfile
高效傳輸:http {sendfile on; # 直接通過內核傳輸文件,減少用戶態/內核態拷貝tcp_nopush on; # 合并TCP包,減少網絡IO }
- 配置緩存頭(
Cache-Control
/Expires
):location ~* \.(js|css|png|jpg)$ {expires 7d; # 瀏覽器緩存7天add_header Cache-Control "public"; }
- 啟用 Gzip 壓縮:
gzip on; gzip_types text/css application/javascript;
10. 如何限制客戶端請求頻率(限流)?
答案:
使用ngx_http_limit_req_module
模塊(漏桶算法):
http {limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s; # 按IP限流,每秒1請求server {location / {limit_req zone=one burst=5 nodelay; # 突發請求允許5個排隊}}
}
Nginx 的驚群問題(Thundering Herd Problem)及解決方案
什么是驚群問題?
????????當多個進程(如 Nginx 的 Worker 進程)同時監聽同一個端口時,若有新的連接請求到達,所有等待該端口的進程會被同時喚醒,但最終只有一個進程能成功處理連接,其他進程會重新進入休眠狀態。這種現象稱為?驚群效應(Thundering Herd Problem)。
影響:頻繁的進程上下文切換會消耗 CPU 資源,降低服務器性能,尤其在高并發場景下更為明顯。Nginx 驚群問題的觸發場景
Nginx 使用?Master-Worker 多進程模型:
- Master 進程:負責管理 Worker 進程,監聽端口并分配連接。
- Worker 進程:多個 Worker 進程共同監聽 Master 進程打開的端口,等待處理客戶端請求。
在舊版本的 Nginx(或未優化配置時),當新連接到達時,所有 Worker 進程會被喚醒并競爭處理連接,導致驚群效應。解決方案:利用?
SO_REUSEPORT
?套接字選項現代操作系統(如 Linux 3.9+、FreeBSD 10+)支持?
SO_REUSEPORT
?選項,允許?多個套接字綁定到同一 IP 地址和端口,內核會自動將連接請求分發到不同的 Worker 進程,避免驚群問題。配置步驟
在 Nginx 配置中啟用?
use_reuseport
:worker_processes 4; # 設置合理的 Worker 進程數(建議等于 CPU 核心數) worker_rlimit_nofile 65535; # 調整文件描述符限制events {worker_connections 1024; # 每個 Worker 進程的最大連接數use epoll; # 使用高效的事件驅動模型(Linux 推薦 epoll)multi_accept on; # 一次盡可能多地接受新連接(可選優化) }http {# 在 http 塊或 server 塊中添加:server {listen 80 reuseport; # 關鍵配置:啟用 SO_REUSEPORTserver_name example.com;# ... 其他配置} }
listen 80 reuseport
:告訴內核使用?SO_REUSEPORT
?選項綁定端口,每個 Worker 進程獨立監聽自己的套接字。worker_processes
?需大于 1,否則無需處理驚群問題。驗證配置生效:
重啟 Nginx 后,通過?ss -ltnp | grep nginx
?查看端口監聽情況,應看到每個 Worker 進程獨立監聽端口:tcp LISTEN 0 128 :::80 :::* users:(("nginx",pid=1234,fd=6),("nginx",pid=1235,fd=6),("nginx",pid=1236,fd=6),("nginx",pid=1237,fd=6))
每個 Worker 進程對應一個獨立的監聽套接字(
fd=6
?是示例文件描述符)。其他優化:
accept_mutex
?鎖(舊方案)在不支持?
?SO_REUSEPORT
?的系統中,Nginx 默認通過?accept_mutex
?互斥鎖?緩解驚群問題:
- 多個 Worker 進程競爭一把鎖,只有獲得鎖的進程才能處理新連接,減少同時喚醒的進程數。
- 配置示例(默認開啟,無需手動設置):
缺點:鎖競爭仍會帶來一定性能損耗,不如?events {accept_mutex on; # 啟用互斥鎖(默認 on)accept_mutex_delay 50ms; # 鎖競爭失敗后的等待時間(默認 50ms) }
SO_REUSEPORT
?高效。
三、負載均衡與代理
11. Nginx 支持哪些負載均衡算法?如何配置?
答案:
- 輪詢(默認):依次分配請求到后端服務器。
upstream backend {server 192.168.1.1;server 192.168.1.2; }
- 權重輪詢(
weight
):按權重分配,適用于性能不均的服務器。server 192.168.1.1 weight=3; # 權重3(默認1)
- IP 哈希(
ip_hash
):相同 IP 固定訪問同一服務器(解決 Session 問題)。upstream backend {ip_hash;server 192.168.1.1; }
- 最少連接(
least_conn
):分配給當前連接最少的服務器。upstream backend {least_conn;server 192.168.1.1; }
- URL 哈希(需自定義模塊,如
ngx_http_upstream_hash_module
):按 URL 哈希值分配。
12. 如何實現后端服務器的健康檢查?
答案:
使用ngx_http_proxy_module
的proxy_next_upstream
指令,配置失敗重試:
upstream backend {server 192.168.1.1 max_fails=3 fail_timeout=30s; # 3次失敗則標記為不可用,30s后重試server 192.168.1.2;
}
location / {proxy_pass http://backend;proxy_next_upstream error timeout http_502 http_504; # 失敗時轉發到下一臺服務器
}
?
13. 反向代理時如何傳遞客戶端真實 IP?
答案:
默認 Nginx 傳遞的X-Forwarded-For
可能被多級代理修改,需配置:
location / {proxy_pass http://backend;proxy_set_header X-Real-IP $remote_addr; # 傳遞真實客戶端IPproxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # 保留代理鏈IP
}
14. 如何配置 Nginx 作為 WebSocket 代理?
答案:
需在proxy_pass
中設置 WebSocket 協議頭:
location /ws/ {proxy_pass http://websocket-server;proxy_http_version 1.1;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection "upgrade";
}
15. 什么是動靜分離?如何實現?
答案:
動靜分離:將靜態資源(如圖片、JS)與動態請求(如 API)分離處理,靜態資源由 Nginx 直接響應,動態請求轉發給后端服務器。
實現方式:
server {location /static/ {root /var/www/app; # 直接返回靜態文件autoindex on; # 開啟目錄瀏覽(可選)}location /api/ {proxy_pass http://backend-api; # 轉發動態請求}
}
四、高級特性與故障處理
16. 如何配置 Nginx 的 HTTP 緩存(Proxy Cache)?
答案:
使用ngx_http_proxy_cache_module
模塊:
http {proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m;proxy_cache_key $scheme$host$request_uri; # 緩存鍵規則server {location / {proxy_pass http://backend;proxy_cache my_cache; # 啟用緩存proxy_cache_valid 200 302 1h; # 200/302響應緩存1小時proxy_cache_valid 404 1m; # 404響應緩存1分鐘}}
}
17. 常見的 502 Bad Gateway 錯誤原因及解決方法?
答案:
原因:
- 后端服務器宕機或未啟動
- 后端服務請求超時(Nginx 等待后端響應超時)
- 負載均衡配置錯誤(如
upstream
服務器地址錯誤) - 后端服務連接數耗盡
解決方法:
- 檢查后端服務狀態(
systemctl status tomcat
等)。 - 調整 Nginx 超時參數:
proxy_connect_timeout 10s; # 連接后端超時 proxy_read_timeout 30s; # 讀取后端響應超時
- 增加后端服務器節點或優化服務性能。
18. 如何查看 Nginx 的實時并發連接數?
答案:
- 使用
nginx -s status
(需配置stub_status
模塊):
訪問location /status {stub_status on;access_log off; }
http://your-nginx/status
查看:Active connections: 123 server accepts handled requests 10000 10000 20000 Reading: 2 Writing: 50 Waiting: 71 # Waiting為空閑keep-alive連接
- 命令行工具:
netstat -ant | grep :80 | wc -l
(統計 80 端口連接數)。
19. 如何實現 Nginx 配置的平滑重啟?
答案:
- 驗證配置正確性:
nginx -t
- 平滑重啟(不中斷現有連接):
nginx -s reload # 重新加載配置 nginx -s reopen # 重新打開日志文件
- 原理:Master 進程生成新 Worker 進程,舊 Worker 處理完剩余請求后退出。
20. 如何禁止 Nginx 記錄特定 URL 的訪問日志?
答案:
在location
中關閉日志記錄:
location /static/ {root /var/www/static;access_log off; # 關閉該路徑的訪問日志
}
五、擴展與實戰
21. 如何為 Nginx 添加自定義模塊?
答案:
- 下載 Nginx 源碼并解壓:
wget http://nginx.org/download/nginx-1.24.0.tar.gz tar -zxvf nginx-1.24.0.tar.gz
- 編譯時添加模塊(以
ngx_http_sub_module
為例):cd nginx-1.24.0 ./configure --add-module=/path/to/module make && make install
- 重啟 Nginx 使模塊生效。
22. 如何配置 Nginx 支持 HTTP/2?
答案:
- 確保編譯時啟用
ngx_http_v2_module
(默認開啟)。 - 配置 HTTPS 并啟用 HTTP/2:
server {listen 443 ssl http2; # 聲明HTTP/2server_name example.com;ssl_certificate /path/to/cert.pem;ssl_certificate_key /path/to/key.pem;# 其他HTTPS優化配置(如TLS版本、加密算法) }
23. 如何實現 Nginx 的請求體大小限制?
答案:
通過client_max_body_size
指令限制(默認 1MB):
http {client_max_body_size 10m; # 允許最大請求體10MBserver {location /upload/ {client_max_body_size 50m; # 針對特定路徑單獨配置}}
}
24. 解釋 Nginx 中root
與alias
的區別
答案:
- root:將請求路徑拼接到配置路徑后查找文件。
例:root /var/www; location /static/
?→ 訪問/static/test.js
對應文件/var/www/static/test.js
。 - alias:直接替換請求路徑為配置路徑。
例:alias /var/www/static/; location /static/
?→ 訪問/static/test.js
對應文件/var/www/static/test.js
。
關鍵區別:alias
會覆蓋location
路徑,root
則拼接路徑;alias
后需加?/
,root
無需。
25. 如何配置 Nginx 的跨域資源共享(CORS)?
答案:
使用add_header
添加 CORS 響應頭:
location /api/ {proxy_pass http://backend;add_header Access-Control-Allow-Origin *; # 允許所有來源add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";add_header Access-Control-Allow-Headers "DNT,User-Agent,Content-Type";if ($request_method = 'OPTIONS') {return 204; # 處理預檢請求}
}
六、性能與安全
26. 如何優化 Nginx 的 SSL/TLS 性能?
答案:
- 啟用 TLS 1.3(比 1.2 更快):
ssl_protocols TLSv1.3 TLSv1.2;
- 選擇高效加密算法:
ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384; ssl_prefer_server_ciphers on;
- 開啟會話緩存(減少握手次數):
ssl_session_cache shared:SSL:10m; ssl_session_timeout 10m;
27. 如何防范 Nginx 的 CC 攻擊(分布式請求偽造)?
答案:
- 限制同一 IP 的并發連接數(
ngx_http_limit_conn_module
):limit_conn_zone $binary_remote_addr zone=conn_limit:10m; server {location / {limit_conn conn_limit 10; # 單個IP最多10個連接limit_conn_status 429; # 超出限制返回429} }
- 結合 WAF(如 ModSecurity)或云防護服務。
28. 解釋 Nginx 中worker_rlimit_nofile
的作用
答案:
該指令用于設置 Worker 進程的最大打開文件數,解決 “Too many open files” 錯誤。
worker_rlimit_nofile 65535; # 單個Worker進程最多打開65535個文件描述符
場景:高并發場景下,需確保該值大于worker_connections
(默認 1024)。
29. 如何實現 Nginx 的請求日志切割?
答案:
- 手動切割:
mv /var/log/nginx/access.log /var/log/nginx/access.log.`date +%Y%m%d` kill -USR1 `cat /var/run/nginx.pid` # 通知Nginx重新生成日志文件
- 自動切割(通過 cron 任務):
0 0 * * * mv /var/log/nginx/access.log /var/log/nginx/access.log.$(date +\%Y\%m\%d) && /usr/sbin/nginx -s reopen
30. 簡述 Nginx 在微服務架構中的應用場景
答案:
- API 網關:統一入口,處理請求路由、限流、認證。
- 靜態資源服務器:獨立部署,減輕后端壓力。
- 服務網格邊緣代理:配合 Istio/Linkerd 處理南北向流量。
- 灰度發布:通過權重輪詢或流量鏡像實現分批次發布。
0voice · GitHub?