一、Nginx 核心概念
????????Nginx(發音為 "engine-x")是一個高性能、開源的 Web 服務器和反向代理服務器,由俄羅斯工程師伊戈爾?賽索耶夫(Igor Sysoev)于 2004 年開發,最初用于解決當時高并發場景下 Apache 服務器的性能瓶頸問題。
核心特點:
- 高并發低資源消耗:采用異步非阻塞(epoll/kqueue)的事件驅動模型,單臺服務器可輕松處理數萬并發連接,內存占用僅幾十 MB(對比 Apache 的進程 / 線程模型,資源消耗更高)。
- 模塊化設計:核心功能通過模塊化擴展(如 HTTP、郵件代理、TCP/UDP 代理),支持動態加載模塊(需編譯時啟用)。
- 反向代理與負載均衡:原生支持反向代理、負載均衡(輪詢、權重、IP 哈希、最少連接等策略),是微服務架構中 API 網關的常見選擇。
- 靜態資源處理高效:對靜態文件(HTML/JS/CSS/ 圖片)的響應速度遠超 Apache,支持文件緩存、壓縮(gzip/brotli)、范圍請求(斷點續傳)。
- 高可靠性:支持熱重載(
nginx -s reload
),修改配置無需重啟服務;Worker 進程獨立運行,單個進程崩潰不影響整體服務。
二、Nginx 典型應用場景
Nginx 憑借其性能優勢,廣泛應用于以下場景:
1. 靜態 Web 服務器
作為靜態資源(HTML / 圖片 / 視頻)的托管服務器,比 Apache 更高效。例如:托管企業官網、前端框架(React/Vue)構建的靜態站點。
2. 反向代理服務器
反向代理是 Nginx 最核心的用途之一:客戶端請求先到 Nginx,由 Nginx 轉發到后端真實服務器(如 Tomcat/Node.js/PHP-FPM),隱藏后端服務器細節,提升安全性。
3. 負載均衡器
通過配置多臺后端服務器,Nginx 可將請求按策略(輪詢、權重、IP 哈希等)分發給不同服務器,避免單節點壓力過大,提升系統可用性。
4. API 網關
結合 Nginx 的請求路由、協議轉換(HTTP/HTTPS)、流量控制(速率限制)、安全過濾(請求頭修改、黑白名單)等功能,作為微服務架構的入口網關。
5. HTTP 緩存服務器
通過proxy_cache
指令緩存后端服務器的響應結果,減少重復請求對后端的壓力,提升用戶訪問速度(如緩存靜態資源或高頻動態接口)。
三、Linux 系統安裝 Nginx
方式 1:通過包管理器安裝(推薦)
# 更新包索引
sudo apt update
# 安裝Nginx
sudo apt install nginx -y
# 啟動服務并設置開機自啟
sudo systemctl start nginx
sudo systemctl enable nginx
方式 2:源碼編譯安裝(自定義功能)
適合需要定制模塊(如ngx_http_ssl_module
/ngx_http_realip_module
)或更高版本的場景:
# 安裝依賴
sudo apt install gcc make libpcre3-dev zlib1g-dev openssl-dev -y # Ubuntu
# 或 sudo yum install gcc make pcre-devel zlib-devel openssl-devel -y (CentOS)# 下載源碼(以1.24.0版本為例)
wget https://nginx.org/download/nginx-1.24.0.tar.gz
tar -zxvf nginx-1.24.0.tar.gz
cd nginx-1.24.0# 配置編譯參數(啟用SSL、gzip等模塊)
./configure \--prefix=/usr/local/nginx \ # 安裝路徑--with-http_ssl_module \ # 啟用HTTPS支持--with-http_gzip_static_module \ # 啟用gzip靜態壓縮--with-http_realip_module # 啟用真實IP獲取(反向代理場景)# 編譯并安裝
make && sudo make install
例如我的./configure如下:
./configure --prefix=/usr/local/nginx --with-http_realip_module --with-http_addition_module --with-http_ssl_module --with-http_gzip_static_module --with-http_secure_link_module --with-http_stub_status_module --with-stream --with-pcre=/home/jerry/snap/nginx/pcre-8.45 --with-zlib=/home/jerry/snap/nginx/zlib-1.2.13 --with-openssl=/home/jerry/snap/nginx/openssl-1.1.1s
四、Nginx 核心配置解析
Nginx 的配置文件默認位于?/etc/nginx/nginx.conf
(包管理器安裝)或?/usr/local/nginx/conf/nginx.conf
(源碼安裝),采用模塊化層級結構,核心包含 3 大塊:
1. 主配置塊(main)
全局配置,影響所有模塊,例如:
user www-data; # 運行Nginx的用戶/用戶組(Ubuntu默認www-data)
worker_processes auto; # Worker進程數(建議設置為CPU核心數,auto自動檢測)
error_log /var/log/nginx/error.log warn; # 錯誤日志路徑及級別(debug/info/warn/error)
pid /run/nginx.pid; # 主進程PID文件路徑# 事件模塊配置(events塊)
events {worker_connections 1024; # 每個Worker進程最大并發連接數use epoll; # 指定事件驅動模型(Linux推薦epoll,FreeBSD用kqueue)
}
當?
worker_processes auto;
?配置下開啟四個進程(worker),且 Nginx 配置文件監聽四個端口(9000~9003)時,完整連接處理過程如下:
Nginx 啟動階段
- Master 進程讀取配置文件,創建 9000~9003 端口的監聽套接字(fd),并開始監聽。
- Master 進程通過?
fork()
?生成四個 worker 進程。每個 worker 進程繼承 master 的監聽套接字(fd),此時所有 worker 進程共享這四個端口的監聽。連接請求到達時
- 當客戶端向某一端口(如 9000)發起連接請求,內核通過負載均衡機制(如?
SO_REUSEPORT
?特性避免驚群效應)選擇一個 worker 進程處理該連接。- 被選中的 worker 進程調用?
accept()
?接受連接,生成新的連接套接字(fd),并將該 fd 添加到自身的?epoll
?實例中管理。- 后續該連接的讀 / 寫事件由該 worker 進程通過?
epoll
?監聽和處理(如讀取客戶端請求、返回響應等)。多端口與負載均衡
- 對于 9001~9003 端口,流程類似:每個端口的連接請求由內核分配給某個 worker 進程,worker 進程處理連接并通過自身?
epoll
?管理。- 四個 worker 進程各自獨立維護自己的?
epoll
?實例,分別處理不同端口的連接請求,實現多進程并發處理,充分利用多核性能。事件循環與資源管理
- 每個 worker 進程在自己的事件循環中通過?
epoll
?監聽連接套接字的事件(如可讀、可寫)。- 當連接關閉或發生異常時,worker 進程從?
epoll
?中移除對應 fd,并釋放相關資源。
2. HTTP 塊(http)
定義 HTTP 相關的核心功能,如虛擬主機、反向代理、緩存等,支持嵌套server
(虛擬主機)和location
(路徑匹配)塊:
http {# 全局HTTP配置(對所有server生效)include /etc/nginx/mime.types; # MIME類型映射文件default_type application/octet-stream; # 默認MIME類型(未匹配時)# 日志格式定義(可自定義字段)log_format main '$remote_addr - $remote_user [$time_local] "$request" ''$status $body_bytes_sent "$http_referer" ''"$http_user_agent" "$http_x_forwarded_for"';access_log /var/log/nginx/access.log main; # 訪問日志路徑及格式# 連接超時設置send_timeout 60; # 發送響應超時時間(秒)keepalive_timeout 75; # 長連接超時時間# 靜態資源優化(gzip壓縮)gzip on;gzip_min_length 1k; # 最小壓縮文件大小(小于1KB不壓縮)gzip_types text/plain text/css application/json application/javascript; # 壓縮類型# 虛擬主機(server塊,可定義多個)server {listen 80; # 監聽端口server_name example.com www.example.com; # 綁定域名(支持通配符如*.example.com)root /var/www/example; # 網站根目錄(靜態文件路徑)index index.html index.htm; # 默認索引文件# 路徑匹配(location塊)location / {try_files $uri $uri/ =404; # 嘗試訪問文件/目錄,不存在返回404}# 反向代理示例(轉發/api開頭的請求到后端Node.js服務)location /api/ {proxy_pass http://127.0.0.1:3000/; # 后端服務器地址(注意末尾的/)proxy_set_header Host $host; # 傳遞原始請求頭到后端proxy_set_header X-Real-IP $remote_addr; # 傳遞真實客戶端IPproxy_connect_timeout 10; # 連接后端超時時間(秒)}# 錯誤頁面配置error_page 404 /404.html;error_page 500 502 503 504 /50x.html;}
}
以下是我寫的問卷系統使用的nginx.conf,解析以及優化建議如下:
user root; worker_processes 1;events {worker_connections 1024; }http {include mime.types;default_type application/octet-stream;sendfile on;keepalive_timeout 65;client_max_body_size 30m;# 添加以下配置,用于設置全局的跨域相關響應頭,允許所有域名跨域訪問(生產環境可按需修改為指定域名)add_header 'Access-Control-Allow-Origin' '*';add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';server {listen 80;server_name localhost;#index index.html index.htm default.htm default.html;root /home/jerry/Desktop/questionnare/questionnare-front;location /login {#root /home/jerry/Desktop/questionnare/questionnare-front;try_files $uri $uri/ /login.html;# 針對這個具體的location塊,也可以單獨配置更細化的跨域頭信息,以下是示例(如果全局配置滿足需求可不加)# add_header 'Access-Control-Allow-Origin' '*';# add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';# add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';# add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';}location /reg {#root /home/jerry/Desktop/questionnare/questionnare-front;try_files $uri $uri/ /reg.html;}location /survey {#root /home/jerry/Desktop/questionnare/questionnare-front;try_files $uri $uri/ /survey.html;}location /root {#root /home/jerry/Desktop/questionnare/questionnare-front;try_files $uri $uri/ /root.html;}location /root_create_table{ #在root的開始界面的創建新的問卷#root /home/jerry/Desktop/questionnare/questionnare-front;try_files $uri $uri/ /root_create_table.html;}location /root_table {#root /home/jerry/Desktop/questionnare/questionnare-front;try_files $uri $uri/ /root_table.html;}location /table {#root /home/jerry/Desktop/questionnare/questionnare-front;try_files $uri $uri/ /table.html;}# api相關location塊location /api/mypictures{proxy_pass http://127.0.0.1:8081;# 針對/api開頭的這些接口相關location塊,也添加跨域頭信息(可根據實際需求決定是否和全局配置保持一致或者單獨配置)add_header 'Access-Control-Allow-Origin' '*';add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';}# api相關location塊location /api/mytables{proxy_pass http://127.0.0.1:8081;# 針對/api開頭的這些接口相關location塊,也添加跨域頭信息(可根據實際需求決定是否和全局配置保持一致或者單獨配置)add_header 'Access-Control-Allow-Origin' '*';add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';}location /api/login{proxy_pass http://127.0.0.1:8081;add_header 'Access-Control-Allow-Origin' '*';add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';}location /api/reg{proxy_pass http://127.0.0.1:8081;add_header 'Access-Control-Allow-Origin' '*';add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';}location /api/unreg{proxy_pass http://127.0.0.1:8081;add_header 'Access-Control-Allow-Origin' '*';add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';}location /api/upload{proxy_pass http://127.0.0.1:8081;add_header 'Access-Control-Allow-Origin' '*';add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';}location /api/delete{proxy_pass http://127.0.0.1:8081;add_header 'Access-Control-Allow-Origin' '*';add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';}location /api/root/tables{proxy_pass http://127.0.0.1:8081;add_header 'Access-Control-Allow-Origin' '*';add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';}location /api/root/table_delete{ #刪除特定的表格proxy_pass http://127.0.0.1:8081;add_header 'Access-Control-Allow-Origin' '*';add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';}location /api/root/table_create{ #刪除特定的表格proxy_pass http://127.0.0.1:8081;add_header 'Access-Control-Allow-Origin' '*';add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';}# 添加 Lua 腳本的 location 塊location /test_login {default_type 'text/plain';content_by_lua_file /home/jerry/Desktop/questionnare/questionnare-src/lua/test_login.lua;}location /test_questionnare {default_type 'text/plain';content_by_lua_file /home/jerry/Desktop/questionnare/questionnare-src/lua/test_questionnare.lua;}error_page 500 502 503 504 /50x.html;location = /50x.html {root html;}} }
一、全局配置塊
user root;
- 作用:指定 Nginx 工作進程運行的用戶和用戶組(默認?
nobody
)。- 注意:
- 開發環境可臨時使用?
root
,但生產環境嚴禁使用(權限過高存在安全風險),建議創建專用用戶(如?nginx
?或?www-data
)。- 配置格式:
user <用戶名> [<用戶組>]
,如?user nginx nginx;
。worker_processes 1;
- 作用:設置 Nginx 工作進程(Worker)的數量。
- 解析:
1
?表示僅啟動 1 個 Worker 進程,適用于單核心 CPU 或開發環境。- 生產環境建議:設為?
auto
(自動檢測 CPU 核心數)或顯式指定核心數(如?worker_processes 4;
),充分利用多核性能。二、事件模塊(
events
?塊)?events {worker_connections 1024; }
- 作用:配置 Worker 進程的連接處理策略。
- 解析:
worker_connections 1024
:每個 Worker 進程最多可同時處理的連接數(含監聽連接和客戶端連接)。- 理論最大并發連接數:
worker_processes * worker_connections
,即此處為?1×1024=1024
。- 生產環境建議:根據內存調整,通常設為?
10240
?或更高(如?worker_connections 8192;
)。三、HTTP 核心配置(
http
?塊)?http {include mime.types;default_type application/octet-stream;
include mime.types
:引入 MIME 類型映射文件(默認路徑?/etc/nginx/mime.types
),用于識別文件類型(如?.js
?對應?application/javascript
)。default_type application/octet-stream
:未匹配到 MIME 類型的文件,默認以二進制流形式處理(避免瀏覽器誤解析)。sendfile on;
- 作用:啟用?
sendfile
?系統調用(零拷貝技術),提升靜態文件傳輸效率(減少內核空間與用戶空間的數據拷貝)。- 適用場景:靜態資源服務器、文件下載等場景,建議始終開啟(默認?
off
)。keepalive_timeout 65;
- 作用:設置 HTTP 長連接的超時時間(秒)。
- 解析:客戶端與 Nginx 建立的連接在空閑?
65
?秒后自動關閉,減少無效連接占用資源。client_max_body_size 30m;
- 作用:限制客戶端請求體的最大大小(含文件上傳)。
- 場景:適用于需要上傳文件的場景(如圖片、文檔),
30m
?表示允許最大 30MB 的請求體。四、全局跨域配置
# 全局跨域頭(開發環境可用 *,生產環境需限制具體域名)add_header 'Access-Control-Allow-Origin' '*';add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
- 作用:解決前端與后端的跨域問題(CORS)。
- 解析:
Access-Control-Allow-Origin: *
:允許所有域名跨域(開發環境方便,但生產環境需改為具體域名,如?add_header 'Access-Control-Allow-Origin' 'https://example.com';
)。OPTIONS
?請求處理:前端發送跨域請求時會先發送?OPTIONS
?預檢請求,需允許?OPTIONS
?方法。- 優化建議:將跨域頭移至?
http
?塊頂部,避免在每個?location
?重復配置。五、虛擬主機(
server
?塊)server {listen 80;server_name localhost;
listen 80
:監聽 HTTP 80 端口。server_name localhost
:綁定域名或 IP(此處為本地開發環境,僅響應?localhost
?的請求)。root /home/jerry/Desktop/questionnare/questionnare-front;
- 作用:設置當前虛擬主機的根目錄,用于解析靜態文件路徑。
- 示例:當請求?
/login.html
?時,Nginx 會查找路徑?/home/jerry/Desktop/questionnare/questionnare-front/login.html
。六、靜態資源路由(
location
?塊)1.?
/login
?路由location /login {try_files $uri $uri/ /login.html;}
- 作用:處理?
/login
?路徑的請求。- 解析:
try_files $uri $uri/ /login.html;
:
- 先嘗試訪問請求的 URI(如?
/login
)對應的文件或目錄;- 若不存在,則返回根目錄下的?
login.html
?文件(實現前端路由匹配,避免 404)。- 適用場景:SPA(單頁應用)路由,如 Vue/React 的前端路由。
2. 其他靜態路由(
/reg
,?/survey
?等)location /reg {try_files $uri $uri/ /reg.html;}# 省略 `/survey`, `/root` 等類似配置...
- 作用:與?
/login
?邏輯一致,分別映射到?reg.html
,?survey.html
?等前端頁面。七、API 反向代理(
location
?塊)1.?
/api/mypictures
?接口location /api/mypictures{proxy_pass http://127.0.0.1:8081;# 跨域頭(全局已配置,此處可省略)add_header 'Access-Control-Allow-Origin' '*';# ... 省略重復的跨域頭配置 ...}
- 作用:將以?
/api/mypictures
?開頭的請求轉發到后端服務器?http://127.0.0.1:8081
。- 解析:
proxy_pass
:反向代理的目標地址,末尾不帶?/
?時,請求路徑會保留前綴(如?/api/mypictures
?轉發為?http://127.0.0.1:8081/api/mypictures
)。- 跨域頭優化:全局?
http
?塊已配置跨域頭,此處可刪除重復的?add_header
,避免響應頭冗余。2. 其他 API 接口(
/api/login
,?/api/upload
?等)?location /api/login{proxy_pass http://127.0.0.1:8081;# ... 省略重復的跨域頭配置 ...}
- 共性:所有?
/api/
?開頭的路徑均轉發到后端?8081
?端口,適用于前后端分離架構(前端跑在 Nginx,后端為獨立服務)。- 建議優化:
location /api/ { # 統一匹配所有 /api/ 路徑proxy_pass http://127.0.0.1:8081;proxy_set_header Host $host; # 傳遞原始 Host 頭proxy_set_header X-Real-IP $remote_addr; # 傳遞客戶端真實 IP }
合并為一個?location
?塊,避免重復代碼,提升可維護性。八、Lua 腳本支持(動態請求處理)
location /test_login {default_type 'text/plain';content_by_lua_file /home/jerry/Desktop/questionnare/questionnare-src/lua/test_login.lua;}
- 作用:通過?
ngx_lua
?模塊執行 Lua 腳本,動態生成響應內容(如測試接口、自定義邏輯)。- 依賴:需提前編譯 Nginx 并啟用?
ngx_lua
?模塊(--add-module=/path/to/ngx_lua
)。- 示例場景:
- 臨時測試接口邏輯;
- 動態生成驗證碼、簽名等。
九、錯誤頁面配置
error_page 500 502 503 504 /50x.html;location = /50x.html {root html;}
- 作用:當后端返回 500 系列錯誤時,Nginx 自動返回?
50x.html
?頁面。- 解析:
root html;
:50x.html
?的實際路徑為 Nginx 默認的?html
?目錄(通常為?/usr/share/nginx/html
?或編譯時指定的路徑)。- 注意:若前端項目的錯誤頁面在根目錄(如?
/home/jerry/.../50x.html
),需將?root
?指向前端目錄:location = /50x.html {root /home/jerry/Desktop/questionnare/questionnare-front; }
十、優化建議與注意事項
1. 生產環境改進點
- 用戶權限:
user nginx nginx; # 創建專用用戶(需先 `useradd nginx`)
- Worker 進程數:
worker_processes auto; # 自動適配 CPU 核心數
- 跨域安全:
add_header 'Access-Control-Allow-Origin' 'https://your-domain.com'; # 限制具體域名
- 合并 API 代理:
將多個?/api/
?路徑合并為一個?location
?塊,減少配置冗余。2. 性能優化
- 開啟 Gzip 壓縮:
gzip on; gzip_types text/plain text/css application/json application/javascript;
- 靜態資源緩存:
location /api/ { # 統一匹配所有 /api/ 路徑proxy_pass http://127.0.0.1:8081;proxy_set_header Host $host; # 傳遞原始 Host 頭proxy_set_header X-Real-IP $remote_addr; # 傳遞客戶端真實 IP }
3. 安全加固
- 禁止直接訪問敏感文件:
location ~* \.(php|sh|bak|swp)$ {deny all; # 禁止訪問 PHP、腳本文件、備份文件等 }
- 隱藏 Nginx 版本號:
server_tokens off;
?
五、Nginx 常用操作命令
命令 | 說明 |
---|---|
sudo nginx | 啟動 Nginx 服務 |
sudo nginx -s stop | 強制停止服務(立即終止所有連接) |
sudo nginx -s quit | 優雅停止服務(完成當前請求后退出) |
sudo nginx -s reload | 重新加載配置文件(熱更新,推薦) |
sudo nginx -t | 檢查配置文件語法是否正確 |
sudo nginx -v | 查看 Nginx 版本信息 |
六、Nginx 性能調優建議
- Worker 進程數:設置為 CPU 核心數(
worker_processes auto
),避免進程競爭。 - 連接數優化:
worker_connections
設為 10240(根據內存調整),配合multi_accept on
(允許 Worker 進程一次性接受多個連接)。 - 靜態資源緩存:通過
expires
指令設置客戶端緩存時間(如圖片 / JS/CSS 緩存 30 天)。 - 壓縮配置:啟用
gzip
或brotli
壓縮,減少傳輸流量(僅對文本類文件有效)。 - 日志優化:對靜態資源關閉訪問日志(
access_log off;
),減少 I/O 消耗。
七、常見問題排查
- 502 Bad Gateway:通常是后端服務器無響應(檢查后端服務是否啟動、端口是否開放)。
- 403 Forbidden:可能是 Nginx 用戶(
user
)無權限訪問網站目錄(檢查目錄權限chmod
)。 - 配置修改不生效:未執行
nginx -s reload
(需重載配置)或配置文件語法錯誤(通過nginx -t
檢查)。 - 日志查看:
- 訪問日志:
/var/log/nginx/access.log
(記錄所有請求) - 錯誤日志:
/var/log/nginx/error.log
(記錄異常信息)
- 訪問日志:
八、反向代理(Reverse Proxy)
1. 核心原理
- 角色定位:Nginx 作為客戶端的「代理服務器」,接收所有外部請求,根據規則轉發到后端真實服務器(如 Tomcat/Node.js/Java 服務),并將響應返回給客戶端。
- 核心作用:
- 隱藏后端服務器架構(IP、端口等細節),提升安全性;
- 統一處理跨域、認證、日志等公共邏輯,簡化后端開發;
- 支持協議轉換(如 HTTP ? HTTPS、WebSocket 代理)。
2. 典型配置場景
場景 1:基礎 HTTP 反向代理
需求:將?http://api.example.com
?的請求轉發到后端?192.168.1.100:8080
?服務,并傳遞真實客戶端 IP。
配置示例:
server {listen 80;server_name api.example.com;location / {# 轉發請求到后端服務器(注意結尾的/,與location路徑匹配)proxy_pass http://192.168.1.100:8080/;# 傳遞原始請求頭(Host 用于后端識別域名,X-Real-IP 傳遞真實IP)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_connect_timeout 5s;proxy_read_timeout 30s;proxy_send_timeout 30s;}
}
場景 2:HTTPS 反向代理(代理 HTTPS 后端服務)
需求:后端服務使用 HTTPS 協議(如 Java Spring Boot 服務),Nginx 需轉發 HTTPS 請求。
配置示例:
server {listen 80;server_name secure-api.example.com;location / {# 轉發到 HTTPS 后端(協議為 https://)proxy_pass https://192.168.1.101:8443/;# 信任后端證書(若為自簽名證書需添加)proxy_ssl_verify off;proxy_ssl_certificate /path/to/backend_cert.pem; # 可選:驗證后端證書時使用}
}
場景 3:WebSocket 反向代理
需求:支持前端 WebSocket 連接(ws://chat.example.com
),轉發到后端 WebSocket 服務。
配置示例:
server {listen 80;server_name chat.example.com;location / {# 轉發 WebSocket 請求(需切換協議頭)proxy_pass http://192.168.1.102:8080;# 關鍵配置:升級協議為 WebSocketproxy_http_version 1.1;proxy_set_header Upgrade $http_upgrade;proxy_set_header Connection "upgrade";}
}
場景 4:路徑重寫反向代理
需求:將?http://example.com/app/
?路徑的請求轉發到后端?http://backend:3000/
,并去除路徑前綴?/app
。
配置示例:
server {listen 80;server_name example.com;location /app/ {# 去除路徑前綴 /app,轉發到后端根路徑proxy_pass http://backend:3000/;rewrite ^/app/(.*) /$1 break; # 重寫路徑# 其他通用配置proxy_set_header Host $host;}
}
3. 驗證方法
-
檢查請求頭:
后端服務中打印?X-Real-IP
?或?X-Forwarded-For
?頭,確認是否為客戶端真實 IP。# 示例:用 curl 模擬請求并查看響應頭 curl -H "Host: api.example.com" http://localhost/app/
-
日志驗證:
在 Nginx 訪問日志中添加?$upstream_addr
?字段,查看請求轉發的后端地址:log_format proxy_log '$remote_addr - $remote_user [$time_local] "$request" ''$status $body_bytes_sent "$http_referer" ''"$http_user_agent" "$upstream_addr"'; access_log /var/log/nginx/proxy_access.log proxy_log;
九、負載均衡(Load Balancing)高級應用
1. 負載均衡策略詳解
Nginx 支持多種分配策略,通過?upstream
?塊配置:
策略 | 說明 | 適用場景 |
---|---|---|
輪詢 | 默認策略,依次將請求分發給后端服務器(權重相同則均勻分配)。 | 無狀態服務,服務器性能一致。 |
權重 | weight ?參數指定服務器處理能力(如?weight=3 ?表示處理 3 倍請求)。 | 服務器性能不均場景。 |
IP 哈希 | 按客戶端 IP 的哈希值固定路由到某臺服務器(會話保持)。 | 需要會話保持的場景。 |
最少連接 | 優先將請求分發給當前連接數最少的服務器。 | 長連接較多的場景(如下載服務)。 |
URL 哈希 | 按請求 URL 的哈希值路由(需第三方模塊?ngx_http_upstream_hash )。 | 相同 URL 需固定到同一服務器(如靜態資源緩存)。 |
動態權重 | 根據服務器響應時間動態調整權重(需第三方模塊?ngx_http_upstream_least_time )。 | 實時動態負載均衡。 |
2. 典型配置示例
場景 1:輪詢策略(默認)
需求:將請求均勻分發給 3 臺后端服務器。
配置示例:
http {upstream web_app {server 192.168.1.101:8080;server 192.168.1.102:8080;server 192.168.1.103:8080;}server {listen 80;server_name lb.example.com;location / {proxy_pass http://web_app;proxy_set_header Host $host;}}
}
場景 2:權重策略(性能差異化)
需求:2 臺高性能服務器(權重 2)和 1 臺低性能服務器(權重 1)。
配置示例:
upstream web_app {server 192.168.1.101:8080 weight=2;server 192.168.1.102:8080 weight=2;server 192.168.1.103:8080 weight=1;
}
場景 3:IP 哈希(會話保持)
需求:確保同一客戶端的請求始終路由到同一服務器(如電商購物車場景)。
配置示例:
upstream web_app {ip_hash; # 啟用 IP 哈希策略server 192.168.1.101:8080;server 192.168.1.102:8080;
}
場景 4:最少連接策略
需求:優先將請求分發給當前負載較低的服務器(如視頻流媒體服務)。
配置示例:
upstream web_app {least_conn; # 啟用最少連接策略server 192.168.1.101:8080;server 192.168.1.102:8080;
}
場景 5:健康檢查(避免轉發到故障節點)
需求:自動剔除不可用的后端服務器,并在恢復后重新加入集群。
配置示例(需啟用?ngx_http_upstream_module
):
upstream web_app {server 192.168.1.101:8080 max_fails=2 fail_timeout=30s; # 2次失敗則標記為不可用,30s后重試server 192.168.1.102:8080;server 192.168.1.103:8080 down; # 手動標記為下線(維護狀態)
}
3. 高級配置:會話保持與緩存
會話保持(Sticky Cookies)
通過 Cookie 實現會話固定,確保同一客戶端請求始終路由到同一服務器:
upstream web_app {server 192.168.1.101:8080;server 192.168.1.102:8080;# 生成名為 "sticky" 的 Cookie,值為后端服務器的哈希值sticky cookie srv_id expires=1h domain=.example.com path=/;
}
緩存響應結果
通過?proxy_cache
?減少后端壓力,緩存高頻請求結果:
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"; # 緩存鍵規則upstream web_app {server 192.168.1.101:8080;}server {location / {proxy_pass http://web_app;proxy_cache my_cache; # 啟用緩存proxy_cache_valid 200 302 1h; # 對200/302響應緩存1小時proxy_cache_valid 404 1m; # 對404響應緩存1分鐘}}
}
4. 驗證負載均衡效果
-
模擬請求分發:
使用?curl
?配合循環腳本,發送多個請求并觀察后端服務器日志:# 循環發送10次請求,查看響應來自哪臺服務器 for i in {1..10}; do curl http://lb.example.com; done
-
壓力測試:
使用?ab
(Apache Benchmark)工具測試負載均衡均勻性:
?ab -n 1000 -c 10 http://lb.example.com/
統計結果中?
Requests per second
?應接近后端服務器數量的倍數(如 3 臺服務器則 QPS 約為單臺的 3 倍)。 -
查看 Nginx 狀態頁:
啟用?ngx_http_stub_status_module
?查看 upstream 狀態:
?location /status {stub_status on;access_log off;allow 127.0.0.1; # 僅允許本地訪問deny all; }
訪問?
http://nginx_ip/status
?可查看活躍連接數、請求總數等指標。
?0voice · GitHub?