環(huán)境實(shí)戰(zhàn):從事件驅(qū)動(dòng)到負(fù)載均衡)
1. 項(xiàng)目概述一份來自實(shí)戰(zhàn)的Nginx深度解析筆記最近在整理技術(shù)棧翻出了幾年前學(xué)習(xí)Nginx時(shí)記下的一堆零散筆記。當(dāng)時(shí)為了搞懂這個(gè)“高性能HTTP和反向代理服務(wù)器”沒少花功夫從最基本的安裝啟動(dòng)到復(fù)雜的負(fù)載均衡策略、動(dòng)靜分離配置再到生產(chǎn)環(huán)境下的性能調(diào)優(yōu)和故障排查每一步都踩過坑、交過學(xué)費(fèi)。看著這些密密麻麻的記錄我決定把它們系統(tǒng)性地梳理出來形成這份超詳細(xì)、超精煉的Nginx學(xué)習(xí)筆記。這份筆記不是官方文檔的翻譯也不是簡單命令的羅列而是融合了我個(gè)人在多個(gè)Web項(xiàng)目、微服務(wù)架構(gòu)以及高并發(fā)場景下的實(shí)戰(zhàn)經(jīng)驗(yàn)旨在幫你繞過我走過的彎路直擊核心快速構(gòu)建起對Nginx的體系化認(rèn)知和實(shí)戰(zhàn)能力。無論你是剛接觸運(yùn)維的開發(fā)者還是希望深化Web服務(wù)器理解的架構(gòu)師這份筆記都能提供從入門到精通的清晰路徑。2. Nginx核心概念與架構(gòu)設(shè)計(jì)解析2.1 為什么是Nginx從Apache到事件驅(qū)動(dòng)模型在Web服務(wù)器的世界里Apache曾經(jīng)是絕對的王者但其傳統(tǒng)的多進(jìn)程/多線程MPM模型在高并發(fā)連接下會(huì)消耗大量的內(nèi)存和CPU資源在進(jìn)程/線程的創(chuàng)建、切換和銷毀上。Nginx的橫空出世正是為了解決這一痛點(diǎn)。它的核心在于其事件驅(qū)動(dòng)、異步非阻塞的架構(gòu)。你可以把它想象成一個(gè)超級高效的餐廳服務(wù)員Master進(jìn)程。傳統(tǒng)的Apache模式像是為每一桌客人都安排一個(gè)專屬服務(wù)員一個(gè)工作進(jìn)程或線程客人點(diǎn)菜、等菜、吃飯、結(jié)賬這個(gè)服務(wù)員全程陪同即使客人發(fā)呆思考人生服務(wù)員也得干等著。當(dāng)客人爆滿時(shí)餐廳就需要雇傭成百上千個(gè)服務(wù)員管理成本劇增。而Nginx的Master進(jìn)程就像餐廳經(jīng)理它手下有幾個(gè)通常等于CPU核心數(shù)非常能干的服務(wù)員Worker進(jìn)程。這些Worker服務(wù)員采用了“事件驅(qū)動(dòng)”的工作方式他們手里拿著一張所有桌客人的需求單事件隊(duì)列。當(dāng)一個(gè)客人舉手要加水一個(gè)網(wǎng)絡(luò)請求到達(dá)服務(wù)員A看到后迅速過去加水然后立刻回到中心查看下一項(xiàng)需求可能是客人B要結(jié)賬。他不會(huì)在某一桌客人思考“要不要再來份甜點(diǎn)”時(shí)傻等。這種工作模式使得一個(gè)Worker進(jìn)程可以同時(shí)處理成千上萬個(gè)連接極大地提升了資源利用率和并發(fā)處理能力。這就是為什么Nginx在應(yīng)對C10K甚至C100K問題時(shí)如此游刃有余在同等硬件條件下能夠支撐的并發(fā)連接數(shù)遠(yuǎn)超傳統(tǒng)服務(wù)器。2.2 Nginx核心進(jìn)程模型與配置加載機(jī)制理解了事件驅(qū)動(dòng)模型我們再來拆解Nginx啟動(dòng)后的內(nèi)部世界。當(dāng)你執(zhí)行nginx命令時(shí)會(huì)啟動(dòng)以下進(jìn)程Master Process主進(jìn)程這是整個(gè)Nginx的“大腦”以root權(quán)限運(yùn)行因?yàn)樾枰O(jiān)聽80、443等特權(quán)端口。它的職責(zé)非常純粹讀取并驗(yàn)證配置文件nginx.conf。管理Worker進(jìn)程的生命周期啟動(dòng)、停止、平滑重啟、重新加載配置。它本身不處理任何客戶端請求因此非常輕量、穩(wěn)定。Worker Process工作進(jìn)程這些是真正“干活”的進(jìn)程數(shù)量在配置文件中通過worker_processes指令定義通常設(shè)置為與CPU邏輯核心數(shù)相等auto。它們以普通用戶如nginx或nobody身份運(yùn)行負(fù)責(zé)處理實(shí)際的網(wǎng)絡(luò)連接、讀取請求、執(zhí)行配置中的邏輯如反向代理、靜態(tài)文件服務(wù)并返回響應(yīng)。多個(gè)Worker進(jìn)程之間是平等的共享監(jiān)聽套接字通過操作系統(tǒng)內(nèi)核提供的機(jī)制如epoll、kqueue來高效地接受新連接。Cache Loader 和 Cache Manager進(jìn)程當(dāng)啟用了代理緩存proxy_cache功能時(shí)這兩個(gè)進(jìn)程會(huì)被創(chuàng)建用于管理磁盤上的緩存文件。配置加載流程至關(guān)重要尤其是進(jìn)行線上變更時(shí)。當(dāng)你修改了nginx.conf并執(zhí)行nginx -s reload時(shí)會(huì)發(fā)生以下事情Master進(jìn)程檢查新配置文件的語法是否正確。如果正確Master進(jìn)程會(huì)啟動(dòng)一組新的Worker進(jìn)程。新的Worker進(jìn)程開始工作并加載新的配置。同時(shí)老的Worker進(jìn)程并不會(huì)立即退出它們會(huì)繼續(xù)處理已建立的連接直到這些連接自然結(jié)束完成當(dāng)前請求。所有老連接處理完畢后老的Worker進(jìn)程才優(yōu)雅退出。這個(gè)過程實(shí)現(xiàn)了配置的熱重載服務(wù)不會(huì)中斷對用戶無感知。這是Nginx在生產(chǎn)環(huán)境維護(hù)中一個(gè)極其重要的特性。注意reload是平滑重載配置而reopen是重新打開日志文件stop和quit分別是快速停止和平滑停止服務(wù)務(wù)必分清。生產(chǎn)環(huán)境永遠(yuǎn)優(yōu)先使用nginx -s quit通知Worker優(yōu)雅退出或nginx -s reload。3. 從零到一Nginx安裝、啟動(dòng)與基礎(chǔ)配置實(shí)戰(zhàn)3.1 多平臺(tái)安裝策略與源碼編譯進(jìn)階安裝Nginx主要有兩種方式使用操作系統(tǒng)的包管理器yum,apt和源碼編譯。包管理器安裝簡單快捷適合快速部署和入門。Ubuntu/Debian:sudo apt update sudo apt install nginxCentOS/RHEL:首先需要添加EPEL倉庫對于老版本然后安裝sudo yum install epel-release sudo yum install nginx然而生產(chǎn)環(huán)境我強(qiáng)烈推薦源碼編譯安裝。原因有三1可以獲得最新版本及時(shí)修復(fù)安全漏洞2可以自定義編譯模塊只包含需要的功能減少二進(jìn)制文件大小和潛在攻擊面3可以優(yōu)化編譯參數(shù)針對特定CPU架構(gòu)進(jìn)行性能調(diào)優(yōu)。源碼編譯標(biāo)準(zhǔn)流程安裝依賴sudo apt install build-essential libpcre3 libpcre3-dev zlib1g zlib1g-dev libssl-devUbuntu。下載源碼從nginx.org下載穩(wěn)定版如nginx-1.24.0.tar.gz。解壓并配置tar -zxvf nginx-1.24.0.tar.gz cd nginx-1.24.0 ./configure --prefix/usr/local/nginx \ --with-http_ssl_module \ --with-http_v2_module \ --with-http_realip_module \ --with-http_stub_status_module \ --with-threads這里--prefix指定安裝目錄--with-http_ssl_module啟用HTTPS支持--with-http_stub_status_module啟用狀態(tài)監(jiān)控頁面這對運(yùn)維至關(guān)重要。編譯與安裝make sudo make install。編譯完成后Nginx的可執(zhí)行文件位于/usr/local/nginx/sbin/nginx配置文件在/usr/local/nginx/conf/nginx.conf。3.2 核心配置文件 nginx.conf 逐層拆解默認(rèn)的nginx.conf結(jié)構(gòu)清晰遵循嵌套的指令塊模式。我們自上而下理解# 全局塊影響Nginx整體運(yùn)行的配置 user nginx; # 定義運(yùn)行Worker進(jìn)程的用戶和組出于安全考慮不應(yīng)使用root worker_processes auto; # Worker進(jìn)程數(shù)設(shè)為auto通常是最佳實(shí)踐 error_log /var/log/nginx/error.log warn; # 錯(cuò)誤日志路徑和級別debug, info, notice, warn, error pid /run/nginx.pid; # 主進(jìn)程PID文件位置 # Events塊影響Nginx與用戶網(wǎng)絡(luò)連接的配置 events { worker_connections 1024; # 單個(gè)Worker進(jìn)程最大并發(fā)連接數(shù)??傋畲筮B接數(shù) worker_processes * worker_connections use epoll; # 在Linux上使用epoll事件驅(qū)動(dòng)模型高性能的關(guān)鍵 multi_accept on; # 允許一個(gè)Worker同時(shí)接受多個(gè)新連接 } # Http塊Nginx作為HTTP服務(wù)器的核心配置可以嵌套多個(gè)Server塊 http { include /etc/nginx/mime.types; # 引入MIME類型映射文件使Nginx能正確識別文件類型如.css, .js default_type application/octet-stream; # 默認(rèn)MIME類型當(dāng)無法識別時(shí)使用 # 日志格式定義 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; # 訪問日志路徑和格式 sendfile on; # 開啟高效文件傳輸模式對于靜態(tài)文件服務(wù)性能提升巨大 tcp_nopush on; # 在sendfile開啟時(shí)合并數(shù)據(jù)包再發(fā)送減少網(wǎng)絡(luò)報(bào)文數(shù)量 tcp_nodelay on; # 對小數(shù)據(jù)包禁用Nagle算法降低延遲適用于高交互場景 keepalive_timeout 65; # 客戶端長連接超時(shí)時(shí)間秒 types_hash_max_size 2048; # 引入其他配置文件實(shí)現(xiàn)模塊化管理 include /etc/nginx/conf.d/*.conf; # include /etc/nginx/sites-enabled/*; # 另一種常見的引入方式 }關(guān)鍵參數(shù)解析與調(diào)優(yōu)建議worker_connections這個(gè)值不僅受限于Nginx配置更受限于操作系統(tǒng)對單個(gè)進(jìn)程打開文件描述符數(shù)量的限制ulimit -n。你需要確保系統(tǒng)的nofile限制大于worker_connections。可以通過ulimit -n 65535臨時(shí)或修改/etc/security/limits.conf永久來調(diào)整。sendfiletcp_nopushtcp_nodelay這是一組黃金搭檔。sendfile直接在內(nèi)核空間完成文件讀取和網(wǎng)絡(luò)發(fā)送繞過用戶緩沖區(qū)效率極高。tcp_nopush告訴Nginx在數(shù)據(jù)包被填滿或達(dá)到最大段大小MSS后再發(fā)送需要與sendfile on配合。而tcp_nodelay則在連接進(jìn)入keep-alive狀態(tài)后立即發(fā)送數(shù)據(jù)不等待緩沖。通常三者同時(shí)開啟能達(dá)到最佳性能。keepalive_timeout設(shè)置過長會(huì)占用服務(wù)器連接資源設(shè)置過短則增加了頻繁建立TCP連接的開銷。對于API服務(wù)器或負(fù)載均衡器可以適當(dāng)調(diào)低如30秒對于大量靜態(tài)資源的網(wǎng)站可以保持默認(rèn)或稍高。4. 核心功能實(shí)戰(zhàn)Server、Location與反向代理4.1 Server塊虛擬主機(jī)的藝術(shù)Server塊定義了虛擬主機(jī)它允許你在單臺(tái)Nginx服務(wù)器上根據(jù)不同的域名、IP或端口提供多個(gè)獨(dú)立的網(wǎng)站服務(wù)。這是Nginx最常用的功能之一。一個(gè)最基礎(chǔ)的基于域名的虛擬主機(jī)配置如下http { server { listen 80; # 監(jiān)聽80端口 server_name www.example.com example.com; # 匹配的域名多個(gè)用空格隔開 root /var/www/example; # 該站點(diǎn)的根目錄 index index.html index.htm; # 默認(rèn)索引文件 location / { try_files $uri $uri/ 404; # 嘗試按順序?qū)ふ椅募埱蟮腢RI - URI作為目錄 - 返回404 } } server { listen 80; server_name blog.example.com; root /var/www/blog; index index.php index.html; # ... 其他配置例如PHP-FPM處理 } }當(dāng)請求到達(dá)時(shí)Nginx會(huì)根據(jù)Host請求頭來匹配server_name決定由哪個(gè)Server塊來處理。listen指令還可以指定IP如listen 192.168.1.100:80;實(shí)現(xiàn)基于IP的虛擬主機(jī)。4.2 Location塊請求路由的精確制導(dǎo)Location塊位于Server塊內(nèi)部用于對特定的URI路徑進(jìn)行更精細(xì)的配置。它的匹配規(guī)則和優(yōu)先級是面試常考點(diǎn)也是配置中最容易出錯(cuò)的地方。語法location [修飾符] 匹配模式 { ... }匹配規(guī)則與優(yōu)先級從高到低精確匹配location /logo.png只匹配/logo.png這個(gè)精確請求。^~前綴匹配禁止正則location ^~ /static/匹配以/static/開頭的所有URI且一旦匹配成功不再檢查后續(xù)的正則location。~或~*正則匹配location ~ \.(gif|jpg|jpeg)$區(qū)分大小寫location ~* \.(gif|jpg|jpeg)$不區(qū)分大小寫。按在配置文件中出現(xiàn)的順序匹配第一個(gè)匹配成功的正則表達(dá)式會(huì)生效。普通前綴匹配location /api/。匹配以/api/開頭的URI。如果有多個(gè)普通前綴匹配選擇最長匹配的那個(gè)。通用匹配location /。匹配所有請求作為兜底。一個(gè)綜合示例server { listen 80; server_name example.com; location / { # 精確匹配首頁 root /var/www/home; index index.html; } location ^~ /static/ { # 靜態(tài)資源優(yōu)先處理不檢查正則 root /var/www; expires 30d; # 設(shè)置瀏覽器緩存30天性能優(yōu)化關(guān)鍵 add_header Cache-Control public, immutable; } location ~* \.(php|php5)$ { # 動(dòng)態(tài)PHP請求 root /var/www; fastcgi_pass 127.0.0.1:9000; # 轉(zhuǎn)發(fā)給PHP-FPM處理 include fastcgi_params; } location /api/ { # API接口反向代理到后端應(yīng)用 proxy_pass http://backend_server; # backend_server是 upstream 定義的負(fù)載均衡組 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } location / { # 兜底規(guī)則其他所有請求 root /var/www/default; index index.html; } }4.3 反向代理連接前后端的橋梁反向代理是Nginx作為“中間層”的核心功能??蛻舳瞬恢苯釉L問后端應(yīng)用服務(wù)器如Java的Tomcat、Python的Django、Node.js應(yīng)用而是訪問Nginx由Nginx將請求轉(zhuǎn)發(fā)給后端并將響應(yīng)返回給客戶端。這樣做的好處是隱藏了后端服務(wù)器、實(shí)現(xiàn)負(fù)載均衡、提供SSL終結(jié)、進(jìn)行緩存、壓縮等?;A(chǔ)反向代理配置location /app/ { proxy_pass http://localhost:8080/; # 注意結(jié)尾的斜杠 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_pass最關(guān)鍵指令。如果proxy_pass的URL帶路徑如http://backend/prefix/則請求的URI中匹配location的部分會(huì)被替換成proxy_pass的路徑。如果不帶路徑如http://backend則會(huì)將完整的請求URI傳遞給后端。務(wù)必理解這個(gè)差異它是很多代理錯(cuò)誤的根源。proxy_set_header修改轉(zhuǎn)發(fā)給后端的請求頭。Host通常設(shè)為原始請求的HostX-Real-IP將客戶端真實(shí)IP傳遞給后端否則后端看到的是Nginx服務(wù)器的IPX-Forwarded-For追加客戶端IP到代理鏈列表X-Forwarded-Proto告知后端原始請求是HTTP還是HTTPS。反向代理的常見問題與調(diào)優(yōu)超時(shí)設(shè)置后端應(yīng)用響應(yīng)慢可能導(dǎo)致Nginx等待超時(shí)。需要配置proxy_connect_timeout連接后端超時(shí)、proxy_send_timeout發(fā)送請求超時(shí)、proxy_read_timeout讀取響應(yīng)超時(shí)例如設(shè)為60s或根據(jù)業(yè)務(wù)調(diào)整。緩沖區(qū)proxy_buffering on;開啟緩沖區(qū)Nginx會(huì)先接收后端完整的響應(yīng)再傳給客戶端可以優(yōu)化慢客戶端的傳輸。通過proxy_buffer_size和proxy_buffers控制緩沖區(qū)大小。關(guān)閉代理緩沖對于需要實(shí)時(shí)流式傳輸?shù)膱鼍叭绶?wù)器推送、大文件下載可以設(shè)置proxy_buffering off;。5. 高級特性與生產(chǎn)環(huán)境配置5.1 負(fù)載均衡分發(fā)流量的策略與健康檢查當(dāng)單臺(tái)后端服務(wù)器無法承受壓力時(shí)就需要負(fù)載均衡。Nginx的upstream模塊提供了強(qiáng)大的負(fù)載均衡功能。http { upstream backend_cluster { # 負(fù)載均衡算法默認(rèn)是輪詢r(jià)ound-robin # least_conn; # 最少連接數(shù) # ip_hash; # 基于客戶端IP的哈希保證同一IP落到同一后端可用于會(huì)話保持 server 192.168.1.101:8080 weight3 max_fails2 fail_timeout30s; server 192.168.1.102:8080 weight2; server 192.168.1.103:8080 backup; # 備份服務(wù)器當(dāng)其他都不可用時(shí)才啟用 server 192.168.1.104:8080 down; # 標(biāo)記為永久下線用于維護(hù) } server { location / { proxy_pass http://backend_cluster; # ... 其他proxy配置 } } }核心參數(shù)解析weight權(quán)重默認(rèn)為1。權(quán)重越高被分配到的請求比例越大。上面配置中101服務(wù)器將處理大約3/(32)60%的請求。max_fails和fail_timeout定義健康檢查。在fail_timeout時(shí)間內(nèi)如果連續(xù)失敗次數(shù)達(dá)到max_fails則將該服務(wù)器標(biāo)記為不可用在接下來的fail_timeout時(shí)間內(nèi)不再向其轉(zhuǎn)發(fā)請求。這是Nginx被動(dòng)的健康檢查。backup備份服務(wù)器只有在其他所有非備份服務(wù)器都不可用時(shí)才會(huì)被啟用。down手動(dòng)標(biāo)記服務(wù)器為永久不可用。對于更可靠的健康檢查可以考慮使用Nginx Plus商業(yè)版的主動(dòng)健康檢查或者結(jié)合第三方模塊如nginx_upstream_check_module。5.2 動(dòng)靜分離與緩存優(yōu)化極致性能的關(guān)鍵動(dòng)靜分離是將動(dòng)態(tài)請求由應(yīng)用服務(wù)器處理如.php,.jsp和靜態(tài)資源請求如圖片、CSS、JS文件分開處理。靜態(tài)資源由Nginx直接處理效率遠(yuǎn)高于經(jīng)過應(yīng)用服務(wù)器。配置示例server { location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2|ttf|eot)$ { root /path/to/static/files; expires 365d; # 設(shè)置超長過期時(shí)間 add_header Cache-Control public, immutable; access_log off; # 靜態(tài)資源訪問日志通??梢躁P(guān)閉減少磁盤IO } location ~ \.php$ { root /path/to/php/app; fastcgi_pass php-fpm:9000; # ... fastcgi 配置 } }通過expires指令Nginx會(huì)在響應(yīng)頭中添加Expires和Cache-Control指示瀏覽器緩存文件。immutable屬性告訴瀏覽器在過期時(shí)間內(nèi)該資源內(nèi)容永不變無需再發(fā)送條件請求驗(yàn)證這對性能提升顯著。代理緩存對于動(dòng)態(tài)內(nèi)容如果在一定時(shí)間內(nèi)不變也可以由Nginx緩存直接返回給后續(xù)相同請求極大減輕后端壓力。http { proxy_cache_path /data/nginx/cache levels1:2 keys_zonemy_cache:10m inactive60m max_size1g use_temp_pathoff; server { location / { proxy_cache my_cache; proxy_cache_key $scheme$request_method$host$request_uri$is_args$args; # 緩存鍵 proxy_cache_valid 200 302 10m; # 200和302狀態(tài)碼緩存10分鐘 proxy_cache_valid 404 1m; # 404緩存1分鐘 proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504; # 當(dāng)后端出錯(cuò)時(shí)使用過期的緩存 add_header X-Cache-Status $upstream_cache_status; # 在響應(yīng)頭中顯示緩存命中狀態(tài)HIT, MISS, BYPASS等 proxy_pass http://backend; } } }proxy_cache_path定義緩存路徑、內(nèi)存鍵區(qū)大小、緩存失效時(shí)間等。add_header X-Cache-Status是一個(gè)非常有用的調(diào)試工具讓你清楚知道請求是否命中了緩存。5.3 HTTPS安全配置與性能優(yōu)化如今HTTPS已是標(biāo)配。使用Let‘s Encrypt等免費(fèi)證書可以輕松實(shí)現(xiàn)。基礎(chǔ)HTTPS配置server { listen 443 ssl http2; # 啟用HTTP/2性能更好 server_name example.com; ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; # 禁用不安全的TLSv1.0和v1.1 ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; # 安全的加密套件 ssl_prefer_server_ciphers on; ssl_session_cache shared:SSL:10m; # SSL會(huì)話緩存提升握手性能 ssl_session_timeout 10m; # ... 其他location配置 } # HTTP強(qiáng)制跳轉(zhuǎn)HTTPS server { listen 80; server_name example.com; return 301 https://$server_name$request_uri; }關(guān)鍵優(yōu)化點(diǎn)HTTP/2在listen指令中添加http2現(xiàn)代瀏覽器都支持能顯著提升頁面加載速度因?yàn)樗С侄嗦窂?fù)用、頭部壓縮等特性。會(huì)話緩存ssl_session_cache和ssl_session_timeout可以減少客戶端再次連接時(shí)的SSL/TLS握手開銷。OCSP Stapling將證書的OCSP驗(yàn)證響應(yīng)緩存在服務(wù)器端一并發(fā)送給客戶端避免客戶端自己去驗(yàn)證加快握手速度并保護(hù)隱私。配置ssl_stapling on;和ssl_stapling_verify on;并指定ssl_trusted_certificate。6. 運(yùn)維監(jiān)控、故障排查與性能調(diào)優(yōu)6.1 狀態(tài)監(jiān)控與日志分析啟用狀態(tài)模塊在編譯時(shí)加入--with-http_stub_status_module然后在配置中啟用location /nginx_status { stub_status on; access_log off; allow 127.0.0.1; # 只允許本機(jī)訪問安全 deny all; }訪問http://your-server/nginx_status會(huì)返回類似信息Active connections: 291 server accepts handled requests 16630948 16630948 31070465 Reading: 6 Writing: 179 Waiting: 106Active connections當(dāng)前活躍客戶端連接數(shù)。accepts已接受的客戶端連接總數(shù)。handled已處理的連接總數(shù)通常與accepts相同除非達(dá)到資源限制。requests客戶端請求的總數(shù)。Reading正在讀取請求頭的連接數(shù)。Writing正在向客戶端寫入響應(yīng)的連接數(shù)。Waiting保持活動(dòng)連接且當(dāng)前空閑等待請求的連接數(shù)。這是需要重點(diǎn)關(guān)注的值如果持續(xù)很高可能意味著keepalive_timeout設(shè)置過長。日志分析access.log和error.log是排查問題的金礦。可以使用awk,grep,sort,uniq等命令進(jìn)行簡單分析例如查看最頻繁的IPawk {print $1} /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -20對于更復(fù)雜的分析推薦使用GoAccess實(shí)時(shí)終端分析或ELKElasticsearch, Logstash, Kibana堆棧。6.2 常見故障排查實(shí)錄403 Forbidden原因權(quán)限問題。Nginx Worker進(jìn)程用戶如nginx或nobody對網(wǎng)站根目錄沒有讀取(r)和執(zhí)行(x)權(quán)限。排查檢查目錄權(quán)限ls -ld /var/www/確保Nginx用戶至少擁有rx權(quán)限。對于靜態(tài)文件需要r權(quán)限。502 Bad Gateway原因Nginx無法連接到上游服務(wù)器如PHP-FPM、后端應(yīng)用。這是最常見錯(cuò)誤之一。排查檢查上游服務(wù)是否在運(yùn)行systemctl status php-fpm或ps aux | grep java。檢查上游服務(wù)監(jiān)聽的端口和Nginxproxy_pass或fastcgi_pass配置是否一致。檢查防火墻firewall-cmd或iptables是否阻止了連接。查看Nginxerror.log通常會(huì)有更詳細(xì)的連接失敗信息如Connection refused。504 Gateway Time-out原因Nginx在配置的時(shí)間內(nèi)未收到上游服務(wù)器的完整響應(yīng)。排查增大proxy_read_timeout默認(rèn)60s的值。但更重要的是排查后端應(yīng)用為何響應(yīng)慢可能是數(shù)據(jù)庫查詢慢、死鎖、外部API調(diào)用超時(shí)等。地址已被占用 (Address already in use)原因Nginx啟動(dòng)時(shí)要監(jiān)聽的端口如80已被其他進(jìn)程占用。排查使用sudo lsof -i :80或sudo netstat -tlnp | grep :80找出占用進(jìn)程并決定是停止該進(jìn)程還是為Nginx更換端口。配置文件語法錯(cuò)誤 (nginx: configuration file test failed)原因nginx.conf或包含的配置文件存在語法錯(cuò)誤。排查使用nginx -t命令測試配置。它會(huì)精確指出錯(cuò)誤所在行和原因如未閉合的花括號、錯(cuò)誤的指令名等。6.3 性能調(diào)優(yōu)實(shí)戰(zhàn)參數(shù)除了前面提到的worker_processes,worker_connections,sendfile等以下參數(shù)在生產(chǎn)環(huán)境中也值得關(guān)注worker_rlimit_nofile在全局塊設(shè)置調(diào)整Worker進(jìn)程可打開的最大文件描述符數(shù)。應(yīng)設(shè)置為大于worker_connections。例如worker_rlimit_nofile 65535;。gzip壓縮壓縮文本響應(yīng)HTML, CSS, JS, JSON等顯著減少傳輸體積。gzip on; gzip_vary on; gzip_min_length 1024; # 小于此值不壓縮 gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xmlrss text/javascript;連接限制防止惡意爬蟲或CC攻擊。http { limit_conn_zone $binary_remote_addr zoneperip:10m; limit_conn_zone $server_name zoneperserver:10m; server { limit_conn perip 10; # 每個(gè)IP同時(shí)最多10個(gè)連接 limit_conn perserver 100; # 每個(gè)虛擬主機(jī)同時(shí)最多100個(gè)連接 # limit_rate 50k; # 可限制每個(gè)連接的帶寬 } }文件描述符優(yōu)化在Linux系統(tǒng)層面確保/etc/security/limits.conf中為Nginx用戶設(shè)置了足夠的nofile限制例如nginx soft nofile 65535和nginx hard nofile 65535。這份筆記從核心原理到生產(chǎn)實(shí)踐涵蓋了Nginx的絕大多數(shù)關(guān)鍵知識點(diǎn)。技術(shù)的學(xué)習(xí)永無止境最好的方式就是在理解原理的基礎(chǔ)上多動(dòng)手實(shí)踐多查閱官方文檔nginx.org并在自己的項(xiàng)目中不斷嘗試和優(yōu)化。記住每一個(gè)線上問題的解決都會(huì)讓你對這套系統(tǒng)的理解更深一層。