日B视频 亚洲,啪啪啪网站一区二区,91色情精品久久,日日噜狠狠色综合久,超碰人妻少妇97在线,999青青视频,亚洲一区二卡,让本一区二区视频,日韩网站推荐

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Nginx 502 Bad Gateway錯(cuò)誤的成因和排查方法

馬哥Linux運(yùn)維 ? 來源:馬哥Linux運(yùn)維 ? 2026-05-06 11:13 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

引言

502 Bad Gateway 是 Nginx 作為反向代理服務(wù)器時(shí)最常遭遇的錯(cuò)誤狀態(tài)碼。這個(gè)錯(cuò)誤意味著 Nginx 作為網(wǎng)關(guān),成功與后端 upstream 建立了連接,但后端返回了一個(gè)無效響應(yīng),或者在傳輸過程中連接被異常關(guān)閉。表面上 502 只是一個(gè) HTTP 狀態(tài)碼,實(shí)際上它是一系列配置錯(cuò)誤、網(wǎng)絡(luò)故障、后端異常的綜合表現(xiàn)。

本文基于 Nginx 1.26.x/1.27.x(截至 2026 年 4 月的穩(wěn)定版本)、PHP-FPM 8.2/8.3、Node.js 20 LTS/22 LTS 等最新穩(wěn)定版本,系統(tǒng)性地拆解 502 錯(cuò)誤的成因、排查方法、解決方案和預(yù)防策略。文章假設(shè)讀者具備基本的 Linux 運(yùn)維能力、Nginx 配置文件閱讀經(jīng)驗(yàn),以及后端應(yīng)用的調(diào)試基礎(chǔ)。

一、問題場(chǎng)景:為什么需要關(guān)注 502 錯(cuò)誤

1.1 502 是最常見的 Nginx 錯(cuò)誤

在生產(chǎn)環(huán)境中,Nginx 作為入口網(wǎng)關(guān)承接所有外部流量。一旦出現(xiàn) 502 錯(cuò)誤,意味著用戶請(qǐng)求無法正常處理,直接影響業(yè)務(wù)可用性。根據(jù)多個(gè)大型網(wǎng)站的運(yùn)維統(tǒng)計(jì),Nginx 相關(guān)故障中 502 Bad Gateway 占到了 40% 至 60%,是所有 Nginx 錯(cuò)誤碼中出現(xiàn)頻率最高的一種。

業(yè)務(wù)影響量化

用戶點(diǎn)擊鏈接后遭遇 502 頁面,平均停留時(shí)長(zhǎng)不超過 3 秒即會(huì)離開。對(duì)于電商網(wǎng)站,這直接導(dǎo)致購(gòu)物車 abandonment;對(duì)于金融交易系統(tǒng),502 可能意味著交易中斷甚至數(shù)據(jù)不一致;對(duì)于 API 服務(wù),502 會(huì)觸發(fā)客戶端重試風(fēng)暴,進(jìn)一步壓垮后端。行業(yè)通用的估算公式是:每 1% 的 502 錯(cuò)誤率可能導(dǎo)致 0.5% 至 2% 的業(yè)務(wù)損失,具體取決于業(yè)務(wù)類型和用戶耐心度。

根因多樣性與排查復(fù)雜性

502 錯(cuò)誤的根因涵蓋多個(gè)層面:網(wǎng)絡(luò)層(物理鏈路中斷、DNS 解析失敗、防火墻攔截)、傳輸層(TCP 連接被重置、端口未監(jiān)聽)、應(yīng)用層(后端進(jìn)程崩潰、超時(shí)配置不合理、緩沖區(qū)溢出)、系統(tǒng)層(文件描述符耗盡、內(nèi)存不足、內(nèi)核參數(shù)限制)、安全層(SELinux/AppArmor 強(qiáng)制訪問控制、iptables 規(guī)則攔截)。這種多層次性導(dǎo)致同一個(gè) 502 癥狀可能對(duì)應(yīng)完全不同的根因。

多層代理架構(gòu)進(jìn)一步增加了排查難度。現(xiàn)代生產(chǎn)環(huán)境中,請(qǐng)求可能經(jīng)過 CDN → 邊緣 Nginx → 負(fù)載均衡層 → 應(yīng)用 Nginx → 后端服務(wù),其中任何一個(gè)節(jié)點(diǎn)的故障都可能以 502 形式呈現(xiàn)。而日志分散在多個(gè)層級(jí),request_id 串聯(lián)成為必要手段而非可選項(xiàng)。

日志閱讀能力缺失是排查失敗的主因

大量工程師遇到 502 后的第一反應(yīng)是重啟 Nginx 或后端服務(wù),這種做法往往只能短暫恢復(fù)問題,無法根治。更深層的問題在于:Nginx error.log 中已經(jīng)記錄了詳細(xì)的錯(cuò)誤原因,但工程師不知道如何解讀這些日志條目。例如"upstream prematurely closed connection"和"connect() failed (111: Connection refused)"雖然都導(dǎo)致 502,但指向的根因完全不同,處理方式也截然不同。

1.2 502 與 504:同樣的網(wǎng)關(guān)錯(cuò)誤,不同的根因

理解 HTTP 502 與 504 的本質(zhì)區(qū)別,是準(zhǔn)確定位問題的前提。

502 Bad Gateway

Nginx 向 upstream 發(fā)起請(qǐng)求并成功建立連接,但 upstream 返回了非正常的響應(yīng)。這個(gè)響應(yīng)可能是:連接建立后立即關(guān)閉(無任何數(shù)據(jù)返回)、返回了無效的 HTTP 響應(yīng)(格式損壞)、連接被上游設(shè)備中斷(RST 包)、或者 upstream 在協(xié)議層面出現(xiàn)錯(cuò)誤(Nginx 無法解析上游的響應(yīng))。

典型錯(cuò)誤日志:

2026/04/24 0832 [error] 12487#12487: *8921 upstream prematurely closed connection while reading response header of upstream, client: 203.0.113.45, server: api.example.com, request: "GET /api/v2/users HTTP/1.1", upstream: "http://127.0.0.1:8080/api/v2/users", upstream_connection: "9612", upstream_bytes_sent: 0, upstream_bytes_received: 0, upstream_trailers: "X-Request-Id: abc123"
2026/04/24 0918 [error] 12487#12487: *9234 connect() failed (111: Connection refused) while connecting to upstream, client: 198.51.100.23, server: www.example.com, request: "POST /api/orders HTTP/1.1", upstream: "http://127.0.0.1:9000/api/orders", upstream_connection: "128"

504 Gateway Timeout

Nginx 向 upstream 發(fā)起請(qǐng)求并成功建立了 TCP 連接,但 upstream 在規(guī)定時(shí)間內(nèi)沒有返回任何數(shù)據(jù)。超時(shí)觸發(fā)后,Nginx 主動(dòng)關(guān)閉連接并向客戶端返回 504。504 的根因通常是后端處理時(shí)間過長(zhǎng)(數(shù)據(jù)庫查詢阻塞、第三方 API 調(diào)用卡住、計(jì)算密集型任務(wù)卡死),或者 upstream 進(jìn)程處于僵死狀態(tài)(不崩潰但不處理請(qǐng)求)。

典型錯(cuò)誤日志:

2026/04/24 1007 [error] 12487#12487: *10234 upstream timed out (110: Connection timed out) while reading response header of upstream, client: 203.0.113.89, server: api.example.com, request: "GET /api/reports HTTP/1.1", upstream: "http://127.0.0.1:8080/api/reports", upstream_connection: "15623", upstream_bytes_sent: 234, upstream_bytes_received: 0
2026/04/24 1133 [error] 12487#12487: *10891 upstream timed out (110: Connection timed out) after 30000 ms (110: Connection timed out) while connecting to upstream, client: 198.51.100.67, server: www.example.com, request: "POST /api/upload HTTP/1.1", upstream: "http://127.0.0.1:9090/api/upload"

499 Client Closed Request

這不是 Nginx 返回給客戶端的錯(cuò)誤碼,而是 Nginx 記錄的一種狀態(tài),表示客戶端在 upstream 響應(yīng)完成之前主動(dòng)斷開了連接(可能是客戶端超時(shí)、用戶取消請(qǐng)求、Nginx 側(cè)配置了 client_body_timeout 或lingering_timeout 強(qiáng)制關(guān)閉)。499 不算 upstream 的故障,但在高并發(fā)場(chǎng)景下大量出現(xiàn) 499 可能暗示 upstream 處理速度過慢,迫使客戶端等待超時(shí)。

2026/04/24 1245 [info] 12487#12487: *11567 client closed connection while waiting for response, client: 203.0.113.112, server: api.example.com, request: "GET /api/stream HTTP/1.1", upstream: "http://127.0.0.1:8080/api/stream"

500 vs 503 vs 502:細(xì)節(jié)差異

500 Internal Server Error:請(qǐng)求已經(jīng)到達(dá) upstream,upstream 在處理過程中發(fā)生了未捕獲的異?;蚺渲缅e(cuò)誤導(dǎo)致崩潰。這是 upstream 自身的問題,Nginx 只是轉(zhuǎn)發(fā)了上游的錯(cuò)誤響應(yīng)。

503 Service Temporarily Unavailable:upstream 正常工作且能夠響應(yīng),但 Nginx 的限流模塊(limit_req_zone)或連接數(shù)限制(limit_conn_zone)觸發(fā)了降級(jí)。503 通常帶有 Retry-After 頭,暗示客戶端稍后重試。

502 Bad Gateway:upstream 連接失敗或返回了無效響應(yīng)。可能是 upstream 徹底不可用,也可能是連接建立后數(shù)據(jù)交換過程中斷裂。

1.3 典型踩坑場(chǎng)景分類

在多年的生產(chǎn)環(huán)境排障經(jīng)歷中,502 錯(cuò)誤可以歸納為以下典型場(chǎng)景。每個(gè)場(chǎng)景都有其特征性日志和明確的解決路徑。

場(chǎng)景一:upstream 配置錯(cuò)誤

最基礎(chǔ)的配置錯(cuò)誤是 ip:port 寫錯(cuò)或域名解析失敗。Nginx 啟動(dòng)時(shí)不會(huì)驗(yàn)證 upstream 的可到達(dá)性,只有在實(shí)際請(qǐng)求時(shí)才會(huì)嘗試連接。如果配置中寫錯(cuò)了 IP 地址(例如 127.0.0.18 而不是 127.0.0.1),或者端口號(hào)與實(shí)際監(jiān)聽不一致,Nginx 會(huì)在 error.log 中記錄"Connection refused"錯(cuò)誤。

# 錯(cuò)誤配置示例
upstream backend {
  server 127.0.0.1:8081; # 實(shí)際服務(wù)運(yùn)行在 8080 端口
}

# 正確配置
upstream backend {
  server 127.0.0.1:8080;
}

場(chǎng)景二:后端服務(wù)未啟動(dòng)

這是最常見也最容易被忽視的場(chǎng)景。Nginx 進(jìn)程由 systemd 托管可以保證 Nginx 自身的高可用,但后端服務(wù)(PHP-FPM、Node.js 應(yīng)用、Gunicorn、Tomcat 等)可能因?yàn)楦鞣N原因退出:OOM Killer 殺死進(jìn)程、代碼 bug 導(dǎo)致崩潰、依賴的數(shù)據(jù)庫或中間件不可用。Nginx 仍然在運(yùn)行,請(qǐng)求到達(dá)后才發(fā)現(xiàn) upstream 無響應(yīng)。

# systemctl 檢查 PHP-FPM 狀態(tài)
$ systemctl status php-fpm
● php-fpm.service - PHP FastCGI Process Manager
  Loaded: loaded (/usr/lib/systemd/system/php-fpm.service; enabled; vendor preset: enabled)
  Active: inactive (dead) since Thu 2026-04-24 0812 CST; 2h 15min ago
  Main PID: 4521 (code=exited, status=0/SUCCESS)

場(chǎng)景三:超時(shí)設(shè)置過短

Nginx 的默認(rèn)超時(shí)值通常比較保守(proxy_connect_timeout 60s、proxy_read_timeout 60s)。對(duì)于處理時(shí)間較長(zhǎng)的請(qǐng)求(如文件上傳、大數(shù)據(jù)量導(dǎo)出、復(fù)雜數(shù)據(jù)庫查詢、調(diào)用外部 API),默認(rèn)超時(shí)會(huì)導(dǎo)致正常請(qǐng)求被誤殺。

# 默認(rèn)超時(shí)配置(過短)
proxy_read_timeout 60s; # 60秒對(duì)于復(fù)雜查詢不夠

# 優(yōu)化后的超時(shí)配置
proxy_read_timeout 300s; # 根據(jù)業(yè)務(wù)特點(diǎn)調(diào)整
proxy_connect_timeout 10s; # 連接超時(shí)可以保持較短

場(chǎng)景四:緩沖區(qū)配置不當(dāng)

Nginx 使用緩沖區(qū)來暫存 upstream 的響應(yīng)數(shù)據(jù)。當(dāng) upstream 返回大文件或流式數(shù)據(jù)時(shí),緩沖區(qū)配置不足會(huì)導(dǎo)致內(nèi)存溢出或?qū)懭氪疟P臨時(shí)文件,極端情況下會(huì)觸發(fā) 502。緩沖區(qū)滿的癥狀是 error.log 中出現(xiàn)"upstream buffer is too small"或大量臨時(shí)文件被寫入 /var/lib/nginx/proxy。

# 緩沖區(qū)不足的典型日志
2026/04/24 1415 [warn] 12487#12487: *12891 an upstream response is buffered to a temporary file /var/lib/nginx/proxy/0000000123, size: 16384 bytes, expect: 5242880 bytes

場(chǎng)景五:keepalive 配置缺失

HTTP/1.1 默認(rèn)支持 keepalive 連接復(fù)用。如果 upstream 塊中沒有配置 keepalive,Nginx 會(huì)為每個(gè)請(qǐng)求創(chuàng)建新的 TCP 連接。高并發(fā)場(chǎng)景下,頻繁的 TCP 握手/揮手消耗大量資源,可能導(dǎo)致 upstream 過載或連接數(shù)溢出。

# 沒有 keepalive 的 upstream 配置
upstream backend {
  server 127.0.0.1:8080;
}

# 優(yōu)化后:配置 keepalive 連接池
upstream backend {
  server 127.0.0.1:8080;
  keepalive 32; # 保持 32 個(gè)空閑連接
  keepalive_requests 1000; # 每個(gè)連接最多處理 1000 請(qǐng)求
  keepalive_timeout 60s; # 空閑連接保持 60 秒
}

場(chǎng)景六:權(quán)限問題

當(dāng) upstream 使用 Unix Domain Socket 通信時(shí),socket 文件的權(quán)限和所有權(quán)必須與 Nginx worker 進(jìn)程的用戶匹配。PHP-FPM 默認(rèn)使用 www-data 用戶創(chuàng)建 socket,而 Nginx 默認(rèn)使用 nginx 用戶運(yùn)行 worker 進(jìn)程,兩者不匹配時(shí)會(huì)導(dǎo)致"Permission denied"錯(cuò)誤。

# /var/log/nginx/error.log 中的權(quán)限錯(cuò)誤
2026/04/24 1527 [crit] 12487#12487: *13456 connect() to unix:/var/run/php-fpm/www.sock failed (13: Permission denied) while connecting to upstream

SELinux 強(qiáng)制訪問控制是另一個(gè)容易忽視的權(quán)限問題。即使 socket 文件權(quán)限正確,SELinux 策略也可能阻止 Nginx 與后端通信。

二、核心原理與關(guān)鍵概念拆解

2.1 Nginx 處理請(qǐng)求的完整流程

理解 Nginx 內(nèi)部處理請(qǐng)求的各個(gè)階段,是準(zhǔn)確定位 502 根因的基礎(chǔ)。Nginx 采用模塊化架構(gòu),請(qǐng)求處理分為 11 個(gè)階段(phase):post-read、server-rewrite、find-config、rewrite、post-rewrite、preaccess、access、post-access、precontent、content、log。502 錯(cuò)誤主要發(fā)生在 content 階段和 log 階段之間。

連接接受階段

Nginx master 進(jìn)程監(jiān)聽配置的端口(80/443),worker 進(jìn)程通過 accept_mutex 機(jī)制競(jìng)爭(zhēng)接受新連接。在多核系統(tǒng)中,Nginx 默認(rèn)使用 epoll 事件模型高效處理大量并發(fā)連接。關(guān)鍵配置參數(shù):

worker_connections:每個(gè) worker 進(jìn)程可處理的最大連接數(shù)(默認(rèn) 512)

multi_accept on:每個(gè) worker 進(jìn)程盡可能多地接受新連接

use epoll:使用 epoll 事件模型(Linux 高效)

# 查看當(dāng)前 Nginx 連接狀態(tài)
$ ss -s
Total: 298 (kernel 0)
TCP:  185 (estab 142, closed 12, orphaned 0, synrecv 0, timewait 5/0)

Transport Total   IP    IPv6
*     298    -     -
RAW    0     0     0
UDP    12    8     4
TCP    173    166    7
INET   185    174    11
FRAG   0     0     0

$ nginx -V 2>&1 | grep -o'with-http_stub_status_module'
with-http_stub_status_module

# 啟用狀態(tài)頁面查看連接詳情
location /nginx_status {
  stub_status on;
  access_log off;
  allow 127.0.0.1;
  deny all;
}
$ curl http://127.0.0.1/nginx_status
Active connections: 142
server accepts handled requests
1289345 1289345 3456782
Reading: 3 Writing: 12 Waiting: 127

請(qǐng)求解析與 Location 匹配

連接接受后,Nginx 解析 HTTP 請(qǐng)求行和請(qǐng)求頭,根據(jù) server_name(基于 Host header 匹配)和 location 塊(精確匹配或正則匹配)確定請(qǐng)求的處理方式。對(duì)于反向代理配置,請(qǐng)求最終會(huì)進(jìn)入 proxy_pass 或 fastcgi_pass 處理。

# nginx.conf 中的 server 塊和 location 匹配示例
server {
  listen 80;
  server_name api.example.com;

 # 精確匹配 /api/
  location = /api/ {
    proxy_pass http://backend_api;
  }

 # 前綴匹配 /api/v2/
  location /api/v2/ {
    proxy_pass http://backend_v2;
  }

 # 正則匹配(~ 區(qū)分大小寫,~* 不區(qū)分大小寫)
  location ~* ^/api/vd+/users {
    proxy_pass http://backend_users;
  }
}

代理轉(zhuǎn)發(fā)階段

請(qǐng)求匹配到 proxy_pass 或 fastcgi_pass 后,Nginx 作為反向代理與 upstream 通信。反向代理的核心流程:

解析 proxy_pass 指令,確定 upstream 地址

從 upstream 塊中選擇一個(gè) server(默認(rèn)加權(quán)輪詢)

建立與 upstream 的 TCP 連接(觸發(fā) connect 事件)

發(fā)送 HTTP 請(qǐng)求(可能受限于 send_timeout)

接收 upstream 響應(yīng)頭(受限于 proxy_read_timeout)

接收 upstream 響應(yīng)體(受限于 buffer 配置)

將響應(yīng)轉(zhuǎn)發(fā)給客戶端

# 核心 proxy 配置解析
location / {
  proxy_pass http://backend; # 指向 upstream 塊

 # 以下請(qǐng)求頭默認(rèn)會(huì)被傳遞
 # Host: $host
 # X-Real-IP: $remote_addr
 # X-Forwarded-For: $proxy_add_x_forwarded_for
 # X-Forwarded-Proto: $scheme

  proxy_http_version 1.1; # 默認(rèn) 1.0,1.1 支持 chunked 編碼
  proxy_set_header Host$host;
  proxy_set_header X-Real-IP$remote_addr;
  proxy_set_header X-Forwarded-For$proxy_add_x_forwarded_for;
}

響應(yīng)處理與緩沖區(qū)機(jī)制

Nginx 收到 upstream 響應(yīng)后,先將響應(yīng)頭存入proxy_buffer_size(默認(rèn) 4k/8k),響應(yīng)體存入proxy_buffers配置的緩沖區(qū)。如果響應(yīng)體數(shù)據(jù)量超過可用緩沖區(qū)總和,剩余數(shù)據(jù)會(huì)寫入磁盤臨時(shí)文件(受proxy_max_temp_file_size限制,默認(rèn) 1024m)。

緩沖區(qū)滿或?qū)懭肱R時(shí)文件時(shí),Nginx 不會(huì)立即返回 502,但如果 upstream 發(fā)送速度過快且 buffer 機(jī)制未啟用(proxy_buffering off),則可能出現(xiàn)數(shù)據(jù)積壓導(dǎo)致超時(shí)。

# 緩沖區(qū)配置詳解
proxy_buffering on; # 啟用緩沖區(qū)(默認(rèn)開啟)
proxy_buffer_size 128k; # 響應(yīng)頭緩沖區(qū),通常 128k 足夠
proxy_buffers 8 256k; # 8 個(gè) 256k 緩沖區(qū),用于響應(yīng)體
proxy_busy_buffer_size 256k; # 忙碌時(shí)使用的緩沖區(qū)大小
proxy_max_temp_file_size 1024m; # 臨時(shí)文件總大小上限
proxy_temp_file_write_size 128k; # 每次寫入臨時(shí)文件的大小

連接關(guān)閉與 keepalive

HTTP/1.1 默認(rèn)使用 keepalive 保持連接復(fù)用。Nginx 通過keepalive_timeout控制連接保持打開的空閑時(shí)間,通過keepalive_requests限制單個(gè)連接處理的最大請(qǐng)求數(shù)。proxy 模塊通過proxy_http_version 1.1和proxy_set_header Connection ""來管理與 upstream 的 keepalive 連接。

# upstream keepalive 配置
upstream backend {
  server 127.0.0.1:8080;
  keepalive 32; # 保持 32 個(gè)空閑連接
  keepalive_requests 1000;
  keepalive_timeout 60s;
}

location / {
  proxy_pass http://backend;
  proxy_http_version 1.1; # 必須使用 1.1 才能支持 keepalive
  proxy_set_header Connection""; # 清除 Connection 頭
}

2.2 upstream 健康檢查機(jī)制

Nginx upstream 模塊支持被動(dòng)健康檢查,通過 max_fails 和 fail_timeout 參數(shù)實(shí)現(xiàn)故障節(jié)點(diǎn)的自動(dòng)剔除。對(duì)于需要主動(dòng)探測(cè)的場(chǎng)景,可以使用第三方模塊 nginx_upstream_check_module。

被動(dòng)健康檢查

Nginx 默認(rèn)對(duì)每個(gè) upstream server 進(jìn)行被動(dòng)健康檢查。當(dāng)某個(gè) server 連續(xù) max_fails 次連接失?。–onnection refused、timeout 等),Nginx 會(huì)將該 server 標(biāo)記為不可用,持續(xù) fail_timeout 秒后重新嘗試。

# upstream 被動(dòng)健康檢查配置
upstream backend {
  server 127.0.0.1:8080 max_fails=3 fail_timeout=10s;
  server 127.0.0.1:8081 max_fails=3 fail_timeout=10s;
  server 127.0.0.1:8082 max_fails=3 fail_timeout=10s backup;
}

參數(shù)說明:

max_fails:默認(rèn) 1。設(shè)置為 0 則禁用對(duì)該 server 的健康檢查。

fail_timeout:默認(rèn) 10s。既是 server 被判定為不可用后持續(xù)的時(shí)間,也是統(tǒng)計(jì)失敗次數(shù)的時(shí)間窗口。

backup:標(biāo)記為備用服務(wù)器,僅在主服務(wù)器全部不可用時(shí)才啟用。

# 查看 upstream 配置和狀態(tài)
$ nginx -T 2>&1 | grep -A 20"upstream backend"
upstream backend {
  server 127.0.0.1:8080 weight=5 max_fails=3 fail_timeout=10s;
  server 127.0.0.1:8081 weight=3 max_fails=3 fail_timeout=10s;
  server 127.0.0.1:8082 backup;
}

# 觀察 error.log 中標(biāo)記 server 不可用的日志
2026/04/24 0812 [warn] 12487#12487: *2341 upstream server temporarily disabled while connecting to upstream, client: 203.0.113.45, server: api.example.com, request: "GET /api/health HTTP/1.1", upstream: "http://127.0.0.1:8080/api/health"

主動(dòng)健康檢查(nginx_upstream_check_module)

官方 Nginx 不包含主動(dòng)健康檢查模塊,需要使用阿里巴巴開源的 nginx_upstream_check_module。該模塊允許 Nginx 主動(dòng)向后端發(fā)送 TCP/HTTP 心跳包,根據(jù)響應(yīng)判斷 server 是否健康。

# 編譯安裝時(shí)加載模塊
./configure --add-module=/path/to/nginx_upstream_check_module

# upstream 配置中添加主動(dòng)健康檢查
upstream backend {
  server 127.0.0.1:8080;
  server 127.0.0.1:8081;

 # 每隔 3 秒對(duì)所有 server 進(jìn)行檢查
 # 檢查類型為 HTTP,檢查 URI /health
 # 超時(shí) 1 秒,連續(xù)失敗 2 次則標(biāo)記為不可用
  check interval=3000 rise=2 fall=2 timeout=1000type=http;
  check_http_send"HEAD /health HTTP/1.0

";
  check_http_expect_alive http_2xx http_3xx;
}

# 狀態(tài)頁面查看健康檢查結(jié)果
location /upstream_status {
  check_status;
  access_log off;
  allow 127.0.0.1;
  deny all;
}
$ curl http://127.0.0.1/upstream_status
Upstream server status:
backend
 server 127.0.0.1:8080   up   1234567890 ms
 server 127.0.0.1:8081   down  0 ms (2/2)

動(dòng)態(tài) upstream 與服務(wù)發(fā)現(xiàn)

在容器化和微服務(wù)架構(gòu)中,upstream 列表需要?jiǎng)討B(tài)更新。常見方案:

Consul/Etcd + Consul-template 或 etcd dynamical:通過服務(wù)發(fā)現(xiàn)系統(tǒng)維護(hù)后端列表,使用模板工具動(dòng)態(tài)生成 Nginx 配置文件并 reload。

OpenResty + lua-upstream-nginx-module:使用 Lua 腳本直接操作 Nginx upstream 內(nèi)存結(jié)構(gòu),實(shí)現(xiàn)運(yùn)行時(shí)更新。

Nginx Plus 商業(yè)版:原生支持 DNS 發(fā)現(xiàn)和 API 動(dòng)態(tài)修改 upstream。

# consul-template 配置文件示例
upstream backend {
 least_conn;

 {{ range service"backend"}}
 server {{ .Address }}:{{ .Port }};
 {{ end }}
}

2.3 緩沖區(qū)機(jī)制深度解析

緩沖區(qū)是 Nginx 與 upstream 之間數(shù)據(jù)傳輸?shù)暮诵臋C(jī)制。理解緩沖區(qū)的工作方式,能夠解釋許多看似莫名其妙的超時(shí)和 502 錯(cuò)誤。

proxy_buffer_size:響應(yīng)頭緩沖區(qū)

Nginx 收到 upstream 的響應(yīng)狀態(tài)行和響應(yīng)頭后,將其存儲(chǔ)在proxy_buffer_size指定的內(nèi)存區(qū)域中。默認(rèn)值為 4k 或 8k(取決于操作系統(tǒng)頁大?。?duì)于絕大多數(shù) HTTP 響應(yīng)頭,這個(gè)大小足夠。如果 upstream 返回的響應(yīng)頭過大(如大量 Cookie、復(fù)雜 CSP 頭),可能需要增大此值。

# 響應(yīng)頭過大時(shí)的錯(cuò)誤日志
2026/04/24 0933 [warn] 12487#12487: *4521 could not build large header, shoulder increase the size of proxy_buffer_size
# 調(diào)整響應(yīng)頭緩沖區(qū)
proxy_buffer_size 256k; # 增大到 256k

proxy_buffers:響應(yīng)體緩沖區(qū)

響應(yīng)體數(shù)據(jù)塊被緩存在proxy_buffers分配的內(nèi)存緩沖區(qū)中。如果響應(yīng)體總大小超過所有緩沖區(qū)的總?cè)萘浚S鄶?shù)據(jù)會(huì)寫入磁盤臨時(shí)文件。臨時(shí)文件路徑由proxy_temp_path指定(默認(rèn) /var/lib/nginx/proxy)。

# 默認(rèn)配置
proxy_buffers 8 4k/8k; # 8 個(gè)緩沖區(qū),每個(gè) 4k 或 8k

# 大文件下載場(chǎng)景
proxy_buffers 16 32k;
proxy_buffering on; # 確保啟用
proxy_max_temp_file_size 2048m; # 允許最大 2G 臨時(shí)文件
# 出現(xiàn)大量臨時(shí)文件時(shí)的告警日志
2026/04/24 1015 [warn] 12487#12487: *7823 upstream sent chunked body with size larger than the whole proxy buffers space while reading upstream

proxy_busy_buffer_size:忙碌緩沖區(qū)

當(dāng) Nginx 開始向客戶端發(fā)送響應(yīng)時(shí),如果客戶端網(wǎng)絡(luò)速度較慢,Nginx 會(huì)繼續(xù)從 upstream 讀取數(shù)據(jù)并存入緩沖區(qū)。proxy_busy_buffer_size定義了在等待客戶端接收數(shù)據(jù)時(shí)可以使用的最大緩沖區(qū)總大小。默認(rèn)等于proxy_buffer_size或proxy_buffers中的單個(gè)緩沖區(qū)大小。

fastcgi_buffering / uwsgi_buffering / scgi_buffering

對(duì)于 PHP-FPM 環(huán)境,使用 fastcgi_pass 時(shí),緩沖區(qū)配置指令前綴變?yōu)閒astcgi_buffer_。原理與 proxy buffering 完全一致。

# PHP-FPM 環(huán)境緩沖區(qū)配置
fastcgi_buffering on;
fastcgi_buffer_size 128k;
fastcgi_buffers 4 256k;
fastcgi_busy_buffers_size 256k;
fastcgi_max_temp_file_size 1024m;
fastcgi_temp_file_write_size 128k;

2.4 超時(shí)體系全面解析

Nginx 的超時(shí)配置構(gòu)成一個(gè)多層次的體系,不同的超時(shí)指令控制請(qǐng)求處理的不同階段。錯(cuò)誤地設(shè)置超時(shí)是導(dǎo)致 502 和 504 的最常見原因。

proxy_connect_timeout:建立連接的超時(shí)

Nginx 等待與 upstream 建立 TCP 握手完成的超時(shí)。如果 upstream 服務(wù)器的端口未監(jiān)聽或網(wǎng)絡(luò)不通,這個(gè)超時(shí)會(huì)在第一次連接嘗試時(shí)觸發(fā)。默認(rèn)值 60s 通常足夠,但如果 upstream 位于跨地域網(wǎng)絡(luò)或高負(fù)載環(huán)境中,可能需要適當(dāng)調(diào)大。

# 默認(rèn) 60 秒,跨地域場(chǎng)景可調(diào)大
proxy_connect_timeout 60s;

# 高延遲網(wǎng)絡(luò)環(huán)境
proxy_connect_timeout 10s; # 10 秒足夠檢測(cè)出不可達(dá)
# connect timeout 的錯(cuò)誤日志
2026/04/24 1108 [error] 12487#12487: *8921 connect() failed (110: Connection timed out) while connecting to upstream, client: 203.0.113.45, upstream: "http://10.0.1.55:8080/"

proxy_send_timeout:向后端發(fā)送請(qǐng)求的超時(shí)

Nginx 向 upstream 發(fā)送請(qǐng)求體的超時(shí)。對(duì)于 POST/PUT 請(qǐng)求(表單提交、文件上傳、API 調(diào)用),如果請(qǐng)求體數(shù)據(jù)量大或上游處理慢,可能觸發(fā)此超時(shí)。默認(rèn)值 60s。

# 文件上傳等大請(qǐng)求場(chǎng)景
proxy_send_timeout 300s; # 5 分鐘
client_max_body_size 100m; # 允許最大請(qǐng)求體 100M

proxy_read_timeout:讀取后端響應(yīng)的超時(shí)

Nginx 從 upstream 讀取響應(yīng)頭和響應(yīng)體的總超時(shí)。這是生產(chǎn)環(huán)境中最常需要調(diào)整的參數(shù)。默認(rèn)值 60s,對(duì)于復(fù)雜業(yè)務(wù)邏輯、數(shù)據(jù)庫查詢、第三方 API 調(diào)用等場(chǎng)景,60s 往往不夠。

# 長(zhǎng)時(shí)間處理的后端服務(wù)
proxy_read_timeout 300s; # 5 分鐘
proxy_send_timeout 300s;

# 實(shí)時(shí)性要求高的 API
proxy_read_timeout 30s;
# read timeout 的錯(cuò)誤日志
2026/04/24 1245 [error] 12487#12487: *10234 upstream timed out (110: Connection timed out) while reading response header of upstream, client: 198.51.100.23, upstream: "http://127.0.0.1:8080/api/report"

send_timeout:發(fā)送給客戶端的超時(shí)

控制 Nginx 向客戶端發(fā)送數(shù)據(jù)的超時(shí),與 upstream 無關(guān)。如果客戶端網(wǎng)絡(luò)慢或客戶端停滯,Nginx 在send_timeout期間未發(fā)送任何數(shù)據(jù)后會(huì)關(guān)閉連接。這個(gè)超時(shí)不影響 502,但可能導(dǎo)致客戶端收到不完整的響應(yīng)。

# 默認(rèn) 60 秒
send_timeout 60s;

keepalive_timeout:keepalive 空呆時(shí)間

HTTP/1.1 keepalive 連接在空閑狀態(tài)下保持的最大時(shí)間。超過此時(shí)間未收到任何數(shù)據(jù),Nginx 會(huì)主動(dòng)關(guān)閉連接。

# keepalive 超時(shí)設(shè)置
keepalive_timeout 75s; # 默認(rèn) 75 秒
keepalive_requests 1000; # 單連接最大請(qǐng)求數(shù)

超時(shí)時(shí)間的實(shí)際計(jì)算邏輯

多個(gè)超時(shí)參數(shù)可能同時(shí)生效。Nginx 在各個(gè)階段分別計(jì)時(shí):

TCP 連接建立:proxy_connect_timeout

請(qǐng)求體發(fā)送:proxy_send_timeout(從連接建立到請(qǐng)求體發(fā)送完成)

等待響應(yīng)頭:proxy_read_timeout(從請(qǐng)求發(fā)送完成到收到響應(yīng)頭)

讀取響應(yīng)體:proxy_read_timeout 繼續(xù)累積(從收到響應(yīng)頭到響應(yīng)體讀取完成)

三、實(shí)戰(zhàn)步驟與常見排障路徑

3.1 502 問題排查的黃金法則

502 錯(cuò)誤的排查需要遵循系統(tǒng)化的步驟,從表象到根因逐層遞進(jìn)。下列步驟經(jīng)過大量生產(chǎn)環(huán)境驗(yàn)證,可以快速定位絕大多數(shù) 502 問題。

第一步:確認(rèn)是否真的是 502

使用 curl -v 查看詳細(xì)的 HTTP 交互過程,觀察 502 是在哪個(gè)階段發(fā)生的。

$ curl -v http://api.example.com/api/v2/users 2>&1
* About to connect() to api.example.com port 80 (#0)
*  Trying 203.0.113.10...
* Connected to api.example.com (203.0.113.10) port 80 (#0)
> GET /api/v2/users HTTP/1.1
> User-Agent: curl/8.4.0
> Host: api.example.com
> Accept: */*
>
< HTTP/1.1 502 Bad Gateway
< Server: nginx/1.26.2
< Date: Fri, 24 Apr 2026 0812 GMT
< Content-Type: text/html
< Content-Length: 157
< Connection: keep-alive
<
{ [data not shown]
* Connection?#0?to host api.example.com left intact
* Closure expected

從 curl 輸出可以確認(rèn):TCP 連接成功建立(Connected),Nginx 返回了 502 狀態(tài)碼,Server 頭顯示 Nginx 版本為 1.26.2。這說明問題發(fā)生在 Nginx 與 upstream 之間。

第二步:檢查 Nginx 錯(cuò)誤日志

Nginx error.log 是定位 502 根因的第一手資料。配置error_log級(jí)別為 info 或 debug 可以獲取更詳細(xì)的調(diào)試信息,但需要注意日志量激增對(duì)磁盤和性能的影響。

# 實(shí)時(shí)跟蹤 error.log 中的 502 相關(guān)錯(cuò)誤
$ tail -f /var/log/nginx/error.log | grep -E"(502|upstream|connect|timed out)"

# 統(tǒng)計(jì)最近 1000 條日志中各類錯(cuò)誤的數(shù)量
$ awk'/[error]/ {count++} /502/ {502count++} /timed out/ {timeout++} /Connection refused/ {refused++} END {print "Total errors:", count, "502 errors:", 502count, "Timeouts:", timeout, "Connection refused:", refused}'/var/log/nginx/error.log
Total errors: 234 502 errors: 45 Timeouts: 12 Connection refused: 33

# 查看錯(cuò)誤上下文(前后 5 行)
$ grep -C 5"502"/var/log/nginx/error.log | head -100

# 統(tǒng)計(jì) 502 錯(cuò)誤的來源 IP
$ awk'/502/ && /client: / {gsub(/,.*/, "", $6); print $6}'/var/log/nginx/error.log | sort | uniq -c | sort -rn
  23 203.0.113.45
  15 198.51.100.123
   7 192.0.2.89
# error.log 配置建議
error_log /var/log/nginx/error.log warn; # 生產(chǎn)環(huán)境使用 warn 級(jí)別,調(diào)試時(shí)使用 info

# 調(diào)試時(shí)臨時(shí)開啟 debug(僅限測(cè)試環(huán)境)
error_log /var/log/nginx/error.log debug;
# debug 日志量極大,務(wù)必在完成調(diào)試后恢復(fù)

第三步:檢查后端服務(wù)狀態(tài)

后端服務(wù)未啟動(dòng)或異常是最常見的 502 根因。檢查后端進(jìn)程是否存活、端口/socket 是否監(jiān)聽、進(jìn)程資源使用情況。

# 檢查 PHP-FPM 進(jìn)程狀態(tài)
$ systemctl status php-fpm
● php-fpm.service - PHP FastCGI Process Manager
  Loaded: loaded (/usr/lib/systemd/system/php-fpm.service; enabled; vendor preset: enabled)
  Active: active (running) since Thu 2026-04-24 0600 CST; 2h 15min ago
 Main PID: 4521 (php-fpm)
  Status:"祥 system is running..."
  Tasks: 12 (limit: 32768)
  Memory: 245.6M
  CGroup: /system.slice/php-fpm.service
      ├─4521 php-fpm: master process (/etc/php-fpm.conf)
      ├─4522 php-fpm: pool www
      ├─4523 php-fpm: pool www
      └─4524 php-fpm: pool www

# 檢查監(jiān)聽端口
$ ss -tlnp | grep -E':(80|443|8080|9000|php)'
State  Recv-Q  Send-Q  Local Address:Port  Peer Address:Port  Process
LISTEN  0    511   127.0.0.1:9000     0.0.0.0:*      users:(("php-fpm",pid=4522,fd=9),("php-fpm",pid=4523,fd=9))
LISTEN  0    511   0.0.0.0:8080      0.0.0.0:*      users:(("node",pid=3421,fd=18))
LISTEN  0    511   0.0.0.0:80       0.0.0.0:*      users:(("nginx",pid=12487,fd=6),("nginx",pid=12488,fd=6))

# 如果使用 Unix socket
$ ls -la /var/run/php-fpm/
total 8
srwxr-xr-x 3 root www-data www-data 120 Apr 24 06:00 /var/run/php-fpm/
srwxrwxrwx 1 www-data www-data  6 Apr 24 06:00 www.sock

# 測(cè)試 socket 連接性(使用 php-fpm 官方探活接口)
$ SCRIPT_NAME=/ping SCRIPT_FILENAME=/ping REQUEST_METHOD=GET cgi-fcgi -bind-connect /var/run/php-fpm/www.sock
Content-type: text/plain
X-Powered-By: PHP 8.3.8
Status: 200 OK
X-Request-Id: abc123
Free: 1
MPool: enabled
Prober:builtin
Content-Length: 6
OK

# 檢查后端進(jìn)程 CPU 和內(nèi)存占用
$ top -b -n 1 | head -20
top - 0833 up 42 days, 3:22, 2 users, load average: 3.45, 2.89, 2.76
Tasks: 287 total,  5 running, 282 sleeping,  0 stopped,  0 zombie
%Cpu(s): 78.5 us, 12.3 sy, 0.0 ni, 9.2 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
MiB Mem : 32768.0 total,  4523.4 free, 18234.5 used, 10010.1 buff/cache
MiB Swap:  8192.0 total,  8192.0 free,   0.0 used. 11234.3 avail Mem

 PID USER   PR NI  VIRT  RES  SHR S %CPU %MEM   TIME+ COMMAND
4522 www-data 20  0 523456 28934  9212 S 45.2  0.1 234:56 php-fpm
4523 www-data 20  0 512234 24567  8734 S 38.7  0.1 198:34 php-fpm
3421 root   20  0 1245678 456123 23456 S 12.3  1.4  56:78 node

第四步:確認(rèn)網(wǎng)絡(luò)連通性

排除物理網(wǎng)絡(luò)層面的問題。即使 upstream 在本機(jī),也需要驗(yàn)證端口可連接性。

# telnet 測(cè)試端口連通性(交互式命令,Ctrl+] 退出)
$ telnet 127.0.0.1 8080
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is'^]'.

# nc 測(cè)試端口連通性(更現(xiàn)代的方式)
$ nc -zv 127.0.0.1 8080
Connection to 127.0.0.1 8080 port [tcp/*] succeeded!

$ nc -zv 127.0.0.1 9000 -w 3
Connection to 127.0.0.1 9000 port [tcp/*] succeeded!

# 如果是域名形式的 upstream,測(cè)試 DNS 解析
$ dig +short api-backend.internal.example.com
10.0.1.55
10.0.1.56
10.0.1.57

$ nslookup api-backend.internal.example.com

# 測(cè)試 TCP 握手時(shí)間(使用 httping)
$ httping -g http://127.0.0.1:8080/health -c 3
PING 127.0.0.1:8080 (to=127.0.0.1):
connected to 127.0.0.1:8080 (301 bytes), seq=0 time=00.35 ms
connected to 127.0.0.1:8080 (301 bytes), seq=1 time=00.31 ms
connected to 127.0.0.1:8080 (301 bytes), seq=2 time=00.28 ms
--- http://127.0.0.1:8080/ ping statistics ---
3 connects, 3 ok, 0.00% roundtrip loss, 0.0/3.0/0.3/0.4 ms min/avg/max

# iptables/firewalld 規(guī)則檢查
$ iptables -L -n | grep -E'(DROP|REJECT)'| head -20
$ firewall-cmd --list-all 2>/dev/null

第五步:驗(yàn)證 upstream 配置是否正確

檢查 nginx.conf 中 upstream 塊的配置,確保 IP 地址、端口、權(quán)重、備份服務(wù)器等參數(shù)正確。

# 測(cè)試 Nginx 配置語法
$ nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conftestis successful

# 完整輸出配置樹(包含所有 include 文件)
$ nginx -T 2>&1 | head -500

# 檢查特定 upstream 塊的配置
$ nginx -T 2>&1 | grep -A 10"^  upstream backend"

3.2 日志深度解讀

Nginx error.log 中記錄的錯(cuò)誤信息是診斷 502 問題最直接的證據(jù)。不同的錯(cuò)誤信息對(duì)應(yīng)不同的根因和處理方式。

"upstream prematurely closed connection"

表示 Nginx 與 upstream 之間的連接在 Nginx 讀取完響應(yīng)頭之前就被 upstream 主動(dòng)關(guān)閉。這通常意味著 upstream 進(jìn)程崩潰、OOM 被殺、或遭遇了致命錯(cuò)誤。

# 典型日志
2026/04/24 0832 [error] 12487#12487: *8921 upstream prematurely closed connection while reading response header of upstream, client: 203.0.113.45, server: api.example.com, request: "GET /api/v2/users HTTP/1.1", upstream: "http://127.0.0.1:8080/api/v2/users", upstream_connection: "9612", upstream_bytes_sent: 234, upstream_bytes_received: 0

關(guān)鍵字段解讀:

upstream prematurely closed connection:根因,upstream 提前關(guān)閉了連接

upstream_connection: "9612":Nginx 側(cè)連接的標(biāo)識(shí)符,可用于關(guān)聯(lián)同一連接的多次請(qǐng)求

upstream_bytes_sent: 234:已發(fā)送給 upstream 的字節(jié)數(shù)

upstream_bytes_received: 0:從 upstream 收到的字節(jié)數(shù),說明 upstream 尚未返回任何數(shù)據(jù)就被關(guān)閉了

排查步驟:

檢查 upstream 服務(wù)(后端應(yīng)用)的錯(cuò)誤日志,尋找崩潰或 panic 的記錄

檢查系統(tǒng)日志(dmesg、/var/log/messages)是否有關(guān)于 OOM Killer 的記錄

確認(rèn)后端服務(wù)是否因?yàn)榇a bug、資源耗盡而崩潰

# 檢查 dmesg 中的 OOM Killer 記錄
$ dmesg -T | grep -i"oom|killed process"| tail -20
[Thu Apr 24 0800 2026] php-fpm[4522]: oom_reaper: reaped process 4522 (php-fpm), now anon-rss: 0kb, file-rss: 0kb

# 檢查 /var/log/messages 中的相關(guān)記錄
$ grep -i"oom|kill|php-fpm"/var/log/messages | tail -30

"connect() failed (111: Connection refused)"

Nginx 嘗試連接 upstream 時(shí),目標(biāo)端口無進(jìn)程監(jiān)聽。這是配置錯(cuò)誤或后端服務(wù)未啟動(dòng)的明確信號(hào)。

# 典型日志
2026/04/24 0918 [error] 12487#12487: *9234 connect() failed (111: Connection refused) while connecting to upstream, client: 198.51.100.23, server: www.example.com, request: "POST /api/orders HTTP/1.1", upstream: "http://127.0.0.1:9000/api/orders", upstream_connection: "128"

關(guān)鍵字段解讀:

connect() failed:連接建立失敗

(111: Connection refused):系統(tǒng)級(jí) errno,111 = ECONNREFUSED,表示目標(biāo)地址有響應(yīng)但端口未監(jiān)聽(對(duì)比 ENETUNREACH = Network unreachable)

排查步驟:

確認(rèn) upstream 服務(wù)進(jìn)程是否運(yùn)行:systemctl status php-fpm或ss -tlnp

確認(rèn) upstream 配置的 IP:端口是否正確

如果是 Unix socket,確認(rèn) socket 文件是否存在且權(quán)限正確

# 模擬 Nginx 的連接行為
$ strace -e trace=connect -s 200 nginx -s reload 2>&1 | grep -i"connection refused"
# 或者對(duì)已知的后端端口抓包
$ tcpdump -i lo port 9000 -nn 2>&1

"no live upstreams while connecting"

所有 upstream server 都不可用,Nginx 找不到可用的后端節(jié)點(diǎn)。

# 典型日志
2026/04/24 1007 [error] 12487#12487: *10234 no live upstreams while connecting to upstream, client: 203.0.113.89, server: api.example.com, request: "GET /api/health HTTP/1.1"

排查步驟:

檢查 upstream 塊中所有 server 的健康狀態(tài)

可能是所有 server 都觸發(fā)了 max_fails 閾值被暫時(shí)禁用

檢查 Nginx 配置中是否有語法錯(cuò)誤導(dǎo)致 upstream 塊無效

# 檢查 upstream 配置
$ nginx -T 2>&1 | grep -A 15"upstream backend"

# 檢查所有 upstream server 是否都被標(biāo)記為 down
# 在 error.log 中搜索 upstream server 狀態(tài)變化
$ grep"upstream.*server.*down|upstream.*server.*disabled"/var/log/nginx/error.log | tail -20
2026/04/24 0812 [warn] 12487#12487: *234 upstream server 127.0.0.1:8080 is marked as down
2026/04/24 0815 [warn] 12487#12487: *235 upstream server 127.0.0.1:8081 is marked as down

"upstream timed out (110: Connection timed out)"

與 upstream 的連接建立成功,但在 proxy_read_timeout 規(guī)定的時(shí)間內(nèi)未收到響應(yīng),Nginx 主動(dòng)關(guān)閉連接。

# 典型日志 - 響應(yīng)頭超時(shí)
2026/04/24 1133 [error] 12487#12487: *10891 upstream timed out (110: Connection timed out) after 30000 ms (110: Connection timed out) while connecting to upstream, client: 198.51.100.67, server: www.example.com, request: "POST /api/upload HTTP/1.1", upstream: "http://127.0.0.1:9090/api/upload"

# 典型日志 - 讀取響應(yīng)超時(shí)
2026/04/24 1244 [error] 12487#12487: *11567 upstream timed out (110: Connection timed out) while reading response header of upstream, client: 203.0.113.112, server: api.example.com, request: "GET /api/reports HTTP/1.1", upstream: "http://127.0.0.1:8080/api/reports", upstream_connection: "15623"

排查步驟:

檢查后端服務(wù)的處理時(shí)間(數(shù)據(jù)庫查詢、文件 I/O、第三方 API 調(diào)用)

確認(rèn) proxy_read_timeout 設(shè)置是否合理

使用后端應(yīng)用自身的慢查詢?nèi)罩径ㄎ黄款i

# PHP-FPM 慢查詢?nèi)罩?$ grep -i"slow"/var/log/php-fpm/www-slow.log | tail -20
[24-Apr-2026 1112] [pool www] pid 5534
script: /var/www/html/api/report.php
call: mysqli_query
time: 45.234567 s
memory: 128.00M

# Node.js 慢日志(使用 --inspect 配合 APM 工具)
$ journalctl -u node-backend --since"2026-04-24 1100"| grep -i"slow|timeout"

access.log 的 502 占比統(tǒng)計(jì)

通過分析 access.log 中各類狀態(tài)碼的分布,可以量化 502 錯(cuò)誤的嚴(yán)重程度和變化趨勢(shì)。

# 統(tǒng)計(jì) access.log 中各狀態(tài)碼的數(shù)量
$ awk'{code[$9]++} END {for (c in code) print c, code[c]}'/var/log/nginx/access.log | sort -k2 -rn
200 1289345
502 4523
499 1234
304 890
404 567
500 234
503 89

# 計(jì)算 502 錯(cuò)誤率
$ total=$(wc -l < /var/log/nginx/access.log); errors502=$(grep -c?" 502 "?/var/log/nginx/access.log);?echo"scale=4;?$errors502?/?$total?* 100"?| bc
0.3489%

# 按時(shí)間段統(tǒng)計(jì) 502 錯(cuò)誤
$ awk?'$4 ~ /[24/Apr/2026:1[0-2]/ && $9 == 502 {hour[$4]++} END {for (h in hour) print h, hour[h]}'?/var/log/nginx/access.log
[24/Apr/202600:00 +0800] 23
[24/Apr/202600:00 +0800] 45
[24/Apr/202600:00 +0800] 12

# 統(tǒng)計(jì)產(chǎn)生 502 錯(cuò)誤最多的請(qǐng)求路徑
$ awk?'$9 == 502 {path[$7]++} END {for (p in path) print path[p], p}'?/var/log/nginx/access.log | sort -rn | head -10
234 /api/v2/users
189 /api/orders/submit
123 /api/reports/generate
67 /api/payments/callback

日志級(jí)別配置與影響

Nginx 日志級(jí)別從低到高:debug、info、notice、warn、error、crit、alert、emerg。生產(chǎn)環(huán)境建議使用 warn 或 error 級(jí)別,避免 debug 級(jí)別產(chǎn)生過大的日志量。

# 日志級(jí)別說明
debug: 調(diào)試信息,僅在編譯時(shí) --with-debug 啟用
info: 一般信息
notice: 需要注意的信息
warn: 警告信息,可能存在問題但不影響運(yùn)行
error: 錯(cuò)誤信息
crit: 嚴(yán)重錯(cuò)誤,部分功能不可用
alert: 必須立即處理
emerg: 系統(tǒng)不可用
# 配置示例
error_log /var/log/nginx/error.log warn;

# 臨時(shí)開啟 debug(測(cè)試環(huán)境)
error_log /var/log/nginx/error.log debug;

# debug 級(jí)別的連接追蹤
events {
  debug_connection 203.0.113.0/24; # 僅對(duì)特定 IP 開啟 debug
  debug_connection 127.0.0.1;
}

分布式 trace:request_id 串聯(lián)日志

在多層代理架構(gòu)中,單個(gè)請(qǐng)求可能經(jīng)過多個(gè) Nginx 節(jié)點(diǎn)。使用 request_id 將各層日志串聯(lián)起來,可以實(shí)現(xiàn)端到端的請(qǐng)求追蹤。

# Nginx 自動(dòng)生成 $request_id(1.11.0+)
# 格式:16 字節(jié)的十六進(jìn)制隨機(jī)數(shù)

# 在請(qǐng)求頭中傳遞 request_id
location / {
  proxy_pass http://backend;
  proxy_set_header X-Request-ID$request_id;
}

# 在 PHP 中獲取 request_id
$requestId=$_SERVER['HTTP_X_REQUEST_ID'] ??'';

# 在 Node.js 中獲取 request_id
const requestId = req.headers['x-request-id'];

# 查詢串聯(lián)后的日志
$ grep"X-Request-Id: abc12345"/var/log/nginx/error.log
2026/04/24 0832 [error] 12487#12487: *8921 upstream prematurely closed connection..., request_id: "abc12345"
2026/04/24 0833 [error] 4522#4522: *8921 php-fpm: pool www: child exited..., request_id: "abc12345"

$ grep"abc12345"/var/log/php-fpm/www-error.log
[24-Apr-2026 0832 UTC] PHP Fatal error: Allowed memory size of 128M exhaustedin/var/www/html/api/v2/users.php on line 234, request_id: abc12345

3.3 常見場(chǎng)景的排障路徑

場(chǎng)景一:PHP-FPM 進(jìn)程全掛

PHP-FPM 是最常見的后端服務(wù)之一,PHP-FPM 進(jìn)程異常退出是導(dǎo)致 502 的高頻原因。

癥狀識(shí)別

error.log 大量"connect() failed (111: Connection refused) while connecting to upstream"

upstream 指向 php-fpm socket 或端口

curl 測(cè)試直接連接后端也失敗

排查步驟

# 1. 檢查 PHP-FPM 服務(wù)狀態(tài)
$ systemctl status php-fpm
● php-fpm.service - PHP FastCGI Process Manager
  Loaded: loaded (/usr/lib/systemd/system/php-fpm.service; enabled; vendor preset: enabled)
  Active: inactive (dead) since Thu 2026-04-24 0812 CST; 2h 15min ago
 Main PID: 4521 (code=exited, status=0/SUCCESS)

# 2. 檢查 PHP-FPM 主進(jìn)程退出原因
$ journalctl -u php-fpm --since"2026-04-24 0800"--until"2026-04-24 0800"
Apr 24 0812 web01 systemd[1]: php-fpm.service: Main process exited, code=killed, status=9/KILL
Apr 24 0812 web01 systemd[1]: php-fpm.service: Failed with result'signal'.

# 3. 檢查 dmesg 中是否有 OOM Killer 記錄
$ dmesg -T | grep -E"php|oom|killed"| tail -10
[Thu Apr 24 0811 2026] php-fpm[4522]: memory usage 256MB exceedslimit256MB, terminated
[Thu Apr 24 0811 2026] Out of memory: Killed process 4522 total-vm:512MB, anon-rss:256MB file-rss:0KB

# 4. 檢查 PHP-FPM 配置中的進(jìn)程管理參數(shù)
$ grep -E"^pm|^proces|child|memory"/etc/php-fpm/www.conf
pm = dynamic
pm.max_children = 50
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20
pm.max_requests = 500
;emergency_restart_threshold = 10
;emergency_restart_interval = 1m
;process_control_timeout = 10s
php_admin_value[memory_limit] = 256M

# 5. 檢查 PHP-FPM 錯(cuò)誤日志
$ cat /var/log/php-fpm/www-error.log | tail -30
[24-Apr-2026 0810 UTC] PHP Fatal error: Allowed memory size of 268435456 bytes exhausted (tried to allocate 16384 bytes)in/var/www/html/api/v2/users.php on line 145
[24-Apr-2026 0811 UTC] PHP Fatal error: Allowed memory size of 268435456 bytes exhausted (tried to allocate 32768 bytes)in/var/www/html/api/v2/users.php on line 234

解決方案

臨時(shí)恢復(fù)服務(wù):重啟 PHP-FPM

$ systemctl restart php-fpm
$ systemctl status php-fpm
● php-fpm.service - PHP FastCGI Process Manager
  Loaded: loaded (/usr/lib/systemd/system/php-fpm.service; enabled; vendor preset: enabled)
  Active: active (running) since Thu 2026-04-24 1000 CST; 5s ago

長(zhǎng)期優(yōu)化:根據(jù) OOM 日志定位內(nèi)存消耗最大的 PHP 腳本,優(yōu)化代碼或上調(diào) memory_limit

# 臨時(shí)調(diào)高 memory_limit(不推薦作為長(zhǎng)期方案)
$ sed -i's/php_admin_value[memory_limit] = 256M/php_admin_value[memory_limit] = 512M/'/etc/php-fpm/www.conf
$ systemctl restart php-fpm

# 優(yōu)化 pm.max_children(根據(jù)可用內(nèi)存計(jì)算)
# 公式:max_children = (總內(nèi)存 - 操作系統(tǒng)預(yù)留 - 其他服務(wù)內(nèi)存) / 單個(gè) PHP 進(jìn)程內(nèi)存
# 假設(shè)服務(wù)器 32G 內(nèi)存,OS 預(yù)留 4G,MySQL 占用 8G,單個(gè) PHP 進(jìn)程平均 64M
# max_children = (32 - 4 - 8) * 1024 / 64 = 320

根因預(yù)防

配置 PHP-FPM emergency_restart_threshold,當(dāng)進(jìn)程在規(guī)定時(shí)間內(nèi)異常退出次數(shù)超過閾值時(shí)自動(dòng)重啟

配置 OOM Score Adj,使 PHP-FPM 進(jìn)程更容易被 OOM Killer 先選中

使用 PHP 內(nèi)存分析工具(xdebug、memprof)定位內(nèi)存泄漏

場(chǎng)景二:Node.js/Python 后端 CPU 跑滿

后端服務(wù) CPU 跑滿時(shí),請(qǐng)求處理速度急劇下降,Nginx 等待后端響應(yīng)超時(shí),最終導(dǎo)致 502。

癥狀識(shí)別

error.log 出現(xiàn)"upstream timed out"

502 錯(cuò)誤持續(xù)出現(xiàn),但后端進(jìn)程仍在運(yùn)行

系統(tǒng) load average 顯著升高

排查步驟

# 1. 檢查 CPU 使用情況
$ top -b -n 1 -p $(pgrep -d','node)
top - 0815 up 42 days, 3:37, 2 users, load average: 8.45, 6.89, 5.76
Tasks: 12 total,  9 running,  3 sleeping,  0 stopped,  0 zombie
%Cpu(s): 95.5 us, 3.2 sy, 0.0 ni, 1.3 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
 PID USER   PR NI  VIRT  RES  SHR S %CPU %MEM   TIME+  COMMAND
3421 root   20  0 1245678 456123 23456 R 78.5  1.4  2345:56 node
3422 root   20  0 234567 123456  8901 R 15.2  0.4  456:34 node
3423 root   20  0 212345 112234  7802 R  1.2  0.3  123:45 node

# 2. 檢查 Node.js 進(jìn)程的請(qǐng)求隊(duì)列長(zhǎng)度
$ curl -s http://127.0.0.1:8080/metrics | grep -E"nodejs_active_requests|eventloop_lag"
# HELP nodejs_active_requests Number of active requests
# TYPE nodejs_active_requests gauge
nodejs_active_requests 150
# HELP nodejs_eventloop_lag Lag in the Node.js event loop in milliseconds
# TYPE nodejs_eventloop_lag gauge
nodejs_eventloop_lag 5234

# 3. 分析 Node.js 慢日志(如果有)
$ cat /var/log/node-backend/slow.log | tail -20
[SLOW] 2026-04-24T0812.234Z - 5034ms - /api/v2/report - Database query slow
[SLOW] 2026-04-24T0815.567Z - 6123ms - /api/v2/report - Memory allocation high

# 4. Python (Gunicorn) 場(chǎng)景:檢查 worker 狀態(tài)
$ ps aux | grep gunicorn | grep -v grep
root   5621 0.0 2.1 245678 456789 ?    S  Apr23  0:30 gunicorn: master [app]
www-data 5622 95.0 3.2 267890 567890 ?    R  Apr24  234:56 gunicorn: worker [/var/www/app]
www-data 5623 92.0 3.1 259876 543210 ?    R  Apr24  198:34 gunicorn: worker [/var/www/app]

$ curl http://127.0.0.1:8000/syncdict # Gunicorn 同步模式下單個(gè)請(qǐng)求阻塞整個(gè) worker

解決方案

快速止血:增加 worker 進(jìn)程數(shù)量或切換到異步模式

# Node.js: 臨時(shí)增加 cluster worker 數(shù)量
# 編輯 app.js,將 worker 數(shù)量從 4 增加到 8
$ sed -i's/workers: 4/workers: 8/'/etc/node-backend/config.js
$ systemctl restart node-backend

# Python: 增加 Gunicorn worker 數(shù)量,使用異步 worker
$ sed -i's/workers=4/workers=8/'/etc/gunicorn/config.py
$ sed -i's/worker-class=sync/worker-class=uvicorn.workers.UvicornWorker/'/etc/gunicorn/config.py
$ systemctl restart gunicorn

定位瓶頸:使用 profiler 找到 CPU 熱點(diǎn)代碼

# Node.js: 使用 --prof 生成 V8 profiling 數(shù)據(jù)
$kill-USR2 $(pgrep node) # 觸發(fā) profiling
$ sleep 30
$kill-USR2 $(pgrep node) # 停止 profiling
$ node --prof-process isolate-*.log| head -30

優(yōu)化超時(shí)配置:根據(jù)后端處理能力調(diào)整 Nginx 超時(shí)

# upstream 塊中添加合理的超時(shí)配置
upstream backend {
  server 127.0.0.1:8080;
  keepalive 16;
}

location / {
  proxy_pass http://backend;
  proxy_http_version 1.1;
  proxy_set_header Connection "";

  # 根據(jù)后端處理能力調(diào)整超時(shí)
  proxy_connect_timeout 5s;
  proxy_send_timeout 30s;
  proxy_read_timeout 60s;
}

場(chǎng)景三:數(shù)據(jù)庫連接池耗盡

后端服務(wù)依賴數(shù)據(jù)庫,當(dāng)數(shù)據(jù)庫連接池耗盡時(shí),后端請(qǐng)求在等待數(shù)據(jù)庫連接時(shí)阻塞,間接導(dǎo)致 Nginx 側(cè)超時(shí)。

癥狀識(shí)別

502 錯(cuò)誤呈現(xiàn)周期性(如每 30 分鐘出現(xiàn)一次高峰)

后端應(yīng)用日志中大量"connection timeout"或"pool exhausted"

數(shù)據(jù)庫服務(wù)器 CPU/內(nèi)存正常,但連接數(shù)達(dá)到上限

排查步驟

# 1. 檢查 MySQL 連接數(shù)
$ mysql -e"SHOW PROCESSLIST;"| wc -l
145

$ mysql -e"SHOW PROCESSLIST;"| grep -E"Sleep|Query"| head -20
+----+------+-----------+--------------------+---------+------+----------+-----------------------+
| Id | User | Host   | db         | Command | Time | State  | Info         |
+----+------+-----------+--------------------+---------+------+----------+-----------------------+
| 1 | root | localhost | information_schema | Query  |  0 | starting | SHOW PROCESSLIST   |
| 45 | app | web01:456 | myapp_production  | Sleep  | 892 |     | NULL         |
| 46 | app | web01:457 | myapp_production  | Sleep  | 891 |     | NULL         |
| 47 | app | web01:458 | myapp_production  | Sleep  | 890 |     | NULL         |
| 48 | app | web02:123 | myapp_production  | Sleep  | 892 |     | NULL         |
+----+------+-----------+--------------------+---------+------+----------+-----------------------+

# 2. 檢查 MySQL 最大連接數(shù)配置
$ mysql -e"SHOW VARIABLES LIKE 'max_connections';"
+-----------------+-------+
| Variable_name  | Value |
+-----------------+-------+
| max_connections | 151  |
+-----------------+-------+

# 3. 檢查 PHP/Python 應(yīng)用的數(shù)據(jù)庫連接池配置
$ grep -E"max_connections|pool_size|connection_pool"/var/www/html/config/database.php
$connPool= new PDO($dsn,$user,$pass, [
  PDO::ATTR_POOL =>true,
  PDO::ATTR_POOL_SIZE => 20,
]);

# 4. 檢查慢查詢?nèi)罩荆ㄩL(zhǎng)時(shí)間運(yùn)行的 Query 會(huì)占用連接)
$ mysql -e"SHOW GLOBAL STATUS LIKE 'Slow_queries';"
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Slow_queries | 1234 |
+---------------+-------+

$ cat /var/log/mysql/slow-query.log | head -30

解決方案

數(shù)據(jù)庫端優(yōu)化:增加 max_connections,調(diào)優(yōu) wait_timeout

-- 臨時(shí)增加連接數(shù)上限
SETGLOBALmax_connections =500;

-- 檢查并調(diào)優(yōu) wait_timeout(避免 Sleep 連接長(zhǎng)期占用)
SHOWGLOBALVARIABLESLIKE'wait_timeout';
SETGLOBALwait_timeout =600;
SETGLOBALinteractive_timeout =600;

應(yīng)用端優(yōu)化:使用連接池管理,設(shè)置連接超時(shí),快速失敗

// PHP: 使用 Doctrine DBAL 連接池,設(shè)置短超時(shí)
$config =newDoctrineDBALConfiguration();
$config->setDriverChain(['adapter'=>'pdo_mysql']);
$connection = DoctrineDBALManagerRegistry::getConnection([
 'driver'=>'pdo_mysql',
 'host'=>'10.0.1.100',
 'dbname'=>'myapp',
 'user'=>'app',
 'password'=>'xxx',
 'options'=> [
    PDO::ATTR_TIMEOUT =>5, // 5 秒超時(shí)
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
  ],
]);

Nginx 端配置:使用短超時(shí)和快速失敗,避免請(qǐng)求堆積

location / {
  proxy_pass http://backend;
  proxy_connect_timeout 3s;
  proxy_send_timeout 10s;
  proxy_read_timeout 30s;

  # 后端處理過慢時(shí)立即返回 502,不累積請(qǐng)求
  proxy_next_upstream error timeout http_502;
}

場(chǎng)景四:Socket 文件權(quán)限問題

PHP-FPM 使用 Unix Domain Socket 與 Nginx 通信時(shí),socket 文件的權(quán)限和所有權(quán)必須正確配置,否則 Nginx 無法連接 PHP-FPM。

癥狀識(shí)別

error.log 中出現(xiàn)"connect() to unix:/var/run/php-fpm/www.sock failed (13: Permission denied)"

PHP-FPM 進(jìn)程正常運(yùn)行,但 Nginx 返回 502

直接測(cè)試 socket 連通性失敗

排查步驟

# 1. 檢查 socket 文件權(quán)限
$ ls -la /var/run/php-fpm/
total 8
srwxr-xr-x 3 root www-data www-data 120 Apr 24 06:00 /var/run/php-fpm/
srwxrwxrwx 1 www-data www-data  6 Apr 24 06:00 www.sock

# 2. 檢查 Nginx worker 進(jìn)程的用戶
$ ps aux | grep"nginx: worker"| head -3
root   12487 0.0 0.3 56789 23456 ? S  Apr23  0:12 nginx: worker process
root   12488 0.0 0.3 56790 23457 ? S  Apr23  0:11 nginx: worker process

# nginx.conf 中 user 指令
$ grep"^user"/etc/nginx/nginx.conf
user nginx nginx;

# 3. 檢查 PHP-FPM pool 配置中的 listen.owner 和 listen.group
$ grep -E"^listen.|listen.owner|listen.group|listen.mode"/etc/php-fpm/www.conf
listen = /var/run/php-fpm/www.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660

# 4. 測(cè)試 socket 連接性
$ sudo -u nginx php-fpm-test-connection /var/run/php-fpm/www.sock
# 或使用 ss 查看 socket 狀態(tài)
$ ss -x | grep php-fpm
u_str LISTEN 0 511 /var/run/php-fpm/www.sock 12345 users:(("php-fpm",pid=4522,fd=9))

SELinux/AppArmor 攔截檢查

# 檢查 SELinux 狀態(tài)
$ getenforce
Enforcing

# 查看 SELinux 阻止的訪問
$ grep nginx /var/log/audit/audit.log | grep -i"denied|refused"| tail -10
type=AVC msg=audit(1713936000.234 avc: denied { connectto }for pid=12487 comm="nginx"path="/var/run/php-fpm/www.sock"scontext=system_uhttpd_t:s0 tcontext=system_uphp-fpm_t:s0 tclass=unix_stream_socket permissive=0

# 臨時(shí)解決:設(shè)置 SELinux 允許 nginx 連接 php-fpm socket
$ setsebool -P httpd_can_network_connect 1

# 永久解決:添加 SELinux 策略
$ cat > /etc/selinux/local/nginx_php_fpm.te <

解決方案

統(tǒng)一用戶和組

# 方案一:讓 Nginx 和 PHP-FPM 使用相同的用戶
# /etc/php-fpm/www.conf
listen.owner = nginx
listen.group = nginx
listen.mode = 0660

# /etc/nginx/nginx.conf
user nginx nginx;

# 方案二:使用 TCP 連接而非 Unix socket
# /etc/php-fpm/www.conf
listen = 127.0.0.1:9000

# /etc/nginx/nginx.conf
location ~ .php$ {
  fastcgi_pass 127.0.0.1:9000;
}

修復(fù) socket 權(quán)限

$ chown www-data:www-data /var/run/php-fpm
$ chmod 0775 /var/run/php-fpm
$ systemctl restart php-fpm

場(chǎng)景五:反代到 Docker 容器

Docker 容器的網(wǎng)絡(luò)模式、容器健康狀態(tài)、容器重啟策略等都會(huì)影響 Nginx 對(duì)容器的代理行為。

癥狀識(shí)別

upstream 指向 Docker 容器 IP 或映射端口

502 錯(cuò)誤在容器重啟后突然出現(xiàn)

docker ps 顯示容器狀態(tài)不穩(wěn)定

排查步驟

# 1. 檢查容器狀態(tài)
$ docker ps -a
CONTAINER ID  IMAGE      STATUS     PORTS         NAMES
abc123def456  myapp:latest  Up 2 hours   0.0.0.0:8080->8080/tcp web01
def456ghi789  myapp:latest  Restarting   0.0.0.0:8081->8080/tcp web02
ghi789jkl012  myapp:latest  Exited (1) 5m  0.0.0.0:8082->8080/tcp web03

# 2. 檢查容器日志
$ docker logs def456ghi789 --tail 50
[2026-04-24 0800] INFO: Starting server on port 8080
[2026-04-24 0801] ERROR: Database connection failed: connection timeout
[2026-04-24 0801] INFO: Retryingin5 seconds...
[2026-04-24 0806] ERROR: Database connection failed: connection timeout
[2026-04-24 0806] FATAL: Could not connect to database after 5 attempts, exiting

# 3. 檢查 Docker 網(wǎng)絡(luò)模式
$ docker inspect def456ghi789 | grep -A 10"NetworkSettings"
"NetworkSettings": {
 "Bridge":"",
 "SandboxID":"xyz123",
 "Gateway":"172.17.0.1",
 "IPAddress":"172.17.0.8",
 "Ports": {
   "8080/tcp": [
      {
       "HostIp":"0.0.0.0",
       "HostPort":"8081"
      }
    ]
  }
}

# 4. 測(cè)試容器網(wǎng)絡(luò)連通性
$ dockerexec-it abc123def456 ping -c 3 db.internal.example.com
PING db.internal.example.com (10.0.1.100) 56(84) bytes of data.
64 bytes from db.internal.example.com (10.0.1.100): icmp_seq=1 ttl=63 time=0.5 ms

$ dockerexec-it abc123def456 curl -v http://localhost:8080/health
* Connected to localhost:8080 (127.0.0.1) port 8080
< HTTP/1.1 200 OK

# 5. 檢查 Docker daemon 日志
$ journalctl -u docker --since?"2026-04-24 0800"?| tail -50

解決方案

使用 Docker Compose 健康檢查和 depends_on 確保啟動(dòng)順序

# docker-compose.yml
version:'3.8'
services:
db:
 image:mysql:8.0
 healthcheck:
  test:["CMD","mysqladmin","ping","-h","localhost"]
  interval:10s
  timeout:5s
  retries:5

app:
 image:myapp:latest
 depends_on:
  db:
   condition:service_healthy
 healthcheck:
  test:["CMD","curl","-f","http://localhost:8080/health"]
  interval:15s
  timeout:5s
  retries:3
 restart:on-failure

在 Nginx upstream 中使用容器名稱(Docker Compose 網(wǎng)絡(luò)內(nèi))

upstream backend {
  server web01:8080;
  server web02:8080;
  server web03:8080 backup;
}

location / {
  proxy_pass http://backend;
  resolver 127.0.0.11 valid=10s; # Docker 內(nèi)置 DNS
  proxy_set_header Host $host;
}

配置 Nginx upstream 主動(dòng)健康檢查

upstream backend {
  server web01:8080;
  server web02:8080;
  server web03:8080 backup;

  check interval=5000 rise=2 fall=3 timeout=3000 type=http;
  check_http_send "HEAD /health HTTP/1.0

";
  check_http_expect_alive http_2xx;
}

3.4 配置優(yōu)化實(shí)戰(zhàn)

超時(shí)參數(shù)調(diào)優(yōu)

超時(shí)配置是 502 問題的核心配置項(xiàng)。根據(jù)業(yè)務(wù)特點(diǎn)合理設(shè)置超時(shí),可以在保護(hù)后端和保證可用性之間取得平衡。

# 生產(chǎn)環(huán)境推薦的超時(shí)配置
proxy_connect_timeout 10s;  # 連接超時(shí),短即可
proxy_send_timeout 60s;   # 發(fā)送請(qǐng)求超時(shí),根據(jù)請(qǐng)求體大小調(diào)整
proxy_read_timeout 120s;   # 讀取響應(yīng)超時(shí),根據(jù)業(yè)務(wù)處理時(shí)間調(diào)整

# 上傳/下載大文件的場(chǎng)景
client_max_body_size 500m;  # 允許最大請(qǐng)求體 500M
proxy_read_timeout 600s;   # 大文件處理需要更長(zhǎng)超時(shí)

# API 服務(wù)的超時(shí)配置
location /api/ {
  proxy_pass http://backend_api;
  proxy_connect_timeout 5s;
  proxy_send_timeout 30s;
  proxy_read_timeout 60s;

  # 啟用請(qǐng)求緩沖,用于大請(qǐng)求體
  proxy_request_buffering on;
  proxy_buffer_size 256k;
}
# 驗(yàn)證超時(shí)配置生效
$ nginx -T 2>&1 | grep -E"proxy_(connect|send|read)_timeout"
  proxy_connect_timeout 10s;
  proxy_send_timeout 60s;
  proxy_read_timeout 120s;

# 通過壓力測(cè)試驗(yàn)證超時(shí)行為
$ ab -n 100 -c 10 -s 30 http://api.example.com/api/v2/report
# 觀察是否會(huì)因?yàn)槌瑫r(shí)導(dǎo)致 502

緩沖區(qū)優(yōu)化

緩沖區(qū)配置直接影響 Nginx 轉(zhuǎn)發(fā)大量數(shù)據(jù)時(shí)的效率。配置不當(dāng)可能導(dǎo)致內(nèi)存占用過高或頻繁寫入臨時(shí)文件。

# 大流量站點(diǎn)推薦緩沖區(qū)配置
proxy_buffering on;
proxy_buffer_size 256k;   # 響應(yīng)頭緩沖區(qū)
proxy_buffers 16 256k;    # 響應(yīng)體緩沖區(qū),16 * 256k = 4M
proxy_busy_buffer_size 512k; # 忙碌時(shí)緩沖區(qū)

# 臨時(shí)文件配置(用于超過內(nèi)存緩沖區(qū)的響應(yīng))
proxy_max_temp_file_size 2048m; # 臨時(shí)文件總大小上限
proxy_temp_file_write_size 256k; # 單次寫入大小

# 靜態(tài)文件代理(減少后端壓力)
location /static/ {
  proxy_pass http://backend_static;
  proxy_buffering on;
  proxy_cache_valid 200 60m; # 緩存 200 響應(yīng) 60 分鐘
  proxy_cache_valid 404 1m;
}
# 監(jiān)控緩沖區(qū)使用情況
$ watch -n 1'cat /proc/$(pgrep nginx | head -1)/status | grep -E "VmPeak|VmSize|Rss"'
Every 1.0s: cat /proc/12487/status | grep -E"VmPeak|VmSize|Rss"

VmPeak: 524288 kB
VmSize: 498234 kB
Rss:   123456 kB

# 檢查是否有大量臨時(shí)文件
$ ls -lah /var/lib/nginx/proxy/ | wc -l
23
$ du -sh /var/lib/nginx/proxy/
1.2G

Keepalive 配置

HTTP keepalive 可以復(fù)用 TCP 連接,顯著減少連接建立的開銷。在高并發(fā)場(chǎng)景中,合理配置 upstream keepalive 是保護(hù)后端的重要手段。

# upstream keepalive 配置
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;

  # keepalive 配置
  keepalive 32;       # 保持 32 個(gè)空閑連接
  keepalive_requests 1000;  # 單連接最大請(qǐng)求數(shù)
  keepalive_timeout 60s;   # 空閑連接超時(shí)
}

# location 中啟用 HTTP/1.1 和清除 Connection 頭
location / {
  proxy_pass http://backend;

  # 必須使用 HTTP/1.1 才能支持 keepalive
  proxy_http_version 1.1;

  # 清除 Connection 頭,否則 nginx 會(huì)保持短連接
  proxy_set_header Connection "";

  # 可選:添加存活探測(cè)
  proxy_connect_timeout 10s;
}
# 對(duì)比有無 keepalive 的性能差異
# 無 keepalive
$ wrk -t4 -c100 -d30s http://127.0.0.1/api/test
Requests/sec: 1234.56
Latency avg:  45.67ms

# 有 keepalive(32 連接)
$ wrk -t4 -c100 -d30s http://127.0.0.1/api/test
Requests/sec: 4567.89
Latency avg:  12.34ms

# 性能提升約 3.7 倍

3.5 預(yù)防性監(jiān)控

502 錯(cuò)誤率告警

#!/bin/bash
# 監(jiān)控 502 錯(cuò)誤率,超過閾值則告警

LOG_FILE="/var/log/nginx/access.log"
THRESHOLD=1.0 # 閾值 1%

calculate_502_rate() {
  total=$(wc -l /dev/null ||echo0)

 if["$total"-eq 0 ];then
   echo"0"
   return
 fi

  rate=$(echo"scale=4;$errors502/$total* 100"| bc)
 echo"$rate"
}

rate=$(calculate_502_rate)
result=$(echo"$rate>$THRESHOLD"| bc)

if["$result"-eq 1 ];then
 echo"CRITICAL: 502 error rate is${rate}%, threshold is${THRESHOLD}%"
 # 觸發(fā)告警(對(duì)接 Prometheus Alertmanager / Grafana / PagerDuty 等)
  curl -X POST"http://alertmanager:9093/api/v1/alerts"
    -H"Content-Type: application/json"
    -d'[{"labels":{"alertname":"Nginx502High","severity":"critical"}}]'
fi

Prometheus + Grafana 監(jiān)控配置

# prometheus.yml - scrape 配置
scrape_configs:
-job_name:'nginx'
 static_configs:
  -targets:['127.0.0.1:9100']# nginx-vts 或 nginx-exporter

# Grafana 查詢 - 502 錯(cuò)誤率
# Nginx upstream response time (5xx)
sum(rate(nginx_upstream_response_seconds_count{upstream=~".*",status=~"5.."}[5m]))by(upstream)

# Nginx upstream request errors
sum(rate(nginx_upstream_request_errors_total[5m]))by(upstream)

# Nginx connection status
nginx_connections_total{status="active"}
nginx_connections_total{status="reading"}
nginx_connections_total{status="writing"}
nginx_connections_total{status="waiting"}

upstream 響應(yīng)時(shí)間分布

# 使用 awk 分析 access.log 中 upstream 響應(yīng)時(shí)間分布
$ awk -F'"''$2 ~ /upstream/ {
  split($2, parts, " ")
  for (i=1; i<=length(parts); i++) {
? ? ? ? if (parts[i] ~ /upstream_response_time/) {
? ? ? ? ? ? split(parts[i], kv, ":")
? ? ? ? ? ? time = kv[3] + 0
? ? ? ? ? ? if (time < 0.1) bucket["<100ms"]++
? ? ? ? ? ? else if (time < 0.5) bucket["100-500ms"]++
? ? ? ? ? ? else if (time < 1) bucket["500ms-1s"]++
? ? ? ? ? ? else if (time < 5) bucket["1-5s"]++
? ? ? ? ? ? else if (time < 30) bucket["5-30s"]++
? ? ? ? ? ? else bucket[">30s"]++
      total++
      break
    }
  }
}
END {
  for (b in bucket) {
    pct = int(bucket[b] / total * 100)
    printf "%s: %d (%d%%)
", b, bucket[b], pct
  }
}'/var/log/nginx/access.log

<100ms: 12345 (45%)
100-500ms: 9876 (36%)
500ms-1s: 2345 (9%)
1-5s: 1234 (5%)
5-30s: 567 (2%)
>30s: 33 (1%)

四、生產(chǎn)環(huán)境最佳實(shí)踐

4.1 架構(gòu)優(yōu)化

多層 Nginx 架構(gòu)

在大型生產(chǎn)環(huán)境中,建議部署兩層 Nginx:邊緣代理層(Edge Proxy)和應(yīng)用代理層(Application Proxy)。邊緣代理負(fù)責(zé) SSL 終結(jié)、請(qǐng)求日志、基礎(chǔ)安全過濾、靜態(tài)資源緩存;應(yīng)用代理負(fù)責(zé)業(yè)務(wù)路由、upstream 健康檢查、負(fù)載均衡、故障轉(zhuǎn)移。

          Internet
            |
        Edge Proxy (NLB)
        1.1.1.1 / 1.1.1.2
        SSL Termination
        Static Cache
        Rate Limiting
            |
        Application Proxy Cluster
        10.0.1.10 / 10.0.1.11 / 10.0.1.12
        Upstream Health Check
        Load Balancing
        Business Routing
            |
        Backend Services
        +------------+------------+
        |      |      |
      PHP-FPM   Node.js   Python
        |      |      |
      Database  Redis    PostgreSQL
# 邊緣代理層配置 - /etc/nginx/edge.conf
# 處理 SSL 終結(jié)和靜態(tài)資源
server {
  listen 443 ssl http2;
  server_name www.example.com;

  ssl_certificate /etc/nginx/ssl/example.com.crt;
  ssl_certificate_key /etc/nginx/ssl/example.com.key;
  ssl_protocols TLSv1.2 TLSv1.3;
  ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
  ssl_prefer_server_ciphers on;
  ssl_session_cache shared10m;
  ssl_session_timeout 1d;

  # 靜態(tài)資源緩存
  location /static/ {
    proxy_pass http://cdn_backend;
    proxy_cache static_cache;
    proxy_cache_valid 200 7d;
    add_header X-Cache-Status $upstream_cache_status;
  }

  # 動(dòng)態(tài)請(qǐng)求轉(zhuǎn)發(fā)到應(yīng)用代理層
  location / {
    proxy_pass http://app_proxy_cluster;
    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;

    # 限流配置
    limit_req zone=api_limit burst=100 nodelay;
    limit_conn_status 429;
  }
}

# 應(yīng)用代理層配置 - /etc/nginx/app.conf
# 負(fù)責(zé) upstream 健康檢查和負(fù)載均衡
upstream backend_php {
  least_conn;

  server 10.0.1.20:9000 weight=5;
  server 10.0.1.21:9000 weight=5;
  server 10.0.1.22:9000 backup;

  # 主動(dòng)健康檢查
  check interval=3000 rise=2 fall=2 timeout=1000 type=http;
  check_http_send "HEAD /health HTTP/1.0

";
  check_http_expect_alive http_2xx;
}

upstream backend_node {
  ip_hash;

  server 10.0.1.30:8080 weight=3;
  server 10.0.1.31:8080 weight=3;
  server 10.0.1.32:8080 weight=3;
}

server {
  listen 80;
  server_name api.example.com;

  location /api/v1/ {
    proxy_pass http://backend_php;
    include /etc/nginx/conf.d/proxy_params.conf;
  }

  location /api/node/ {
    proxy_pass http://backend_node;
    include /etc/nginx/conf.d/proxy_params.conf;
  }
}

主動(dòng)健康檢查配置

使用 nginx_upstream_check_module 實(shí)現(xiàn)主動(dòng)健康檢查,比被動(dòng)檢查更早發(fā)現(xiàn)故障節(jié)點(diǎn),避免將請(qǐng)求發(fā)往已故障的后端。

# 加載模塊(編譯時(shí)添加)
# ./configure --add-module=/path/to/nginx_upstream_check_module

upstream backend {
  server 127.0.0.1:8080;
  server 127.0.0.1:8081;
  server 127.0.0.1:8082 backup;

  # 主動(dòng)健康檢查配置
  # interval: 檢查間隔 3 秒
  # rise: 連續(xù) 2 次成功則標(biāo)記為 up
  # fall: 連續(xù) 3 次失敗則標(biāo)記為 down
  # timeout: 檢查超時(shí) 1 秒
  # type: 檢查類型為 HTTP
  check interval=3000 rise=2 fall=3 timeout=1000 type=http;

  # 發(fā)送的 HTTP 請(qǐng)求
  check_http_send "HEAD /health HTTP/1.0

";

  # 期望的響應(yīng)狀態(tài)碼
  check_http_expect_alive http_2xx http_3xx;
}

# 健康檢查狀態(tài)頁面
server {
  listen 8080;
  server_name localhost;

  location /upstream_status {
    check_status;
    access_log off;
    allow 127.0.0.1;
    deny all;
  }

  location /health {
    return 200 "OK";
    add_header Content-Type text/plain;
  }
}
# 驗(yàn)證健康檢查狀態(tài)
$ curl http://127.0.0.1:8080/upstream_status
Upstream server status:
backend
 server 127.0.0.1:8080   up   1234567890 ms
 server 127.0.0.1:8081   down  5000 ms (3/3)
 server 127.0.0.1:8082   backup
Total connections: 2345
upstream alive connections: 1234

灰度發(fā)布與權(quán)重調(diào)整

在升級(jí)后端服務(wù)時(shí),使用 Nginx 的權(quán)重調(diào)整實(shí)現(xiàn)流量切換,而非直接替換。新版本接收小部分流量,觀察無異常后逐步增加權(quán)重。

# 金絲雀發(fā)布配置
upstream backend_stable {
  server 127.0.0.1:8080; # 當(dāng)前穩(wěn)定版本
}

upstream backend_canary {
  server 127.0.0.1:8081; # 新版本,權(quán)重為 1
}

# 90% 流量到穩(wěn)定版,10% 到金絲雀
upstream backend {
  server 127.0.0.1:8080 weight=9;
  server 127.0.0.1:8081 weight=1;
}

# 或者根據(jù)請(qǐng)求特征(如 Cookie、Header)分流
map $cookie_canary_version $backend_pool {
  default http://backend_stable;
  "v2" http://backend_canary;
}

location / {
  proxy_pass $backend_pool;
  include /etc/nginx/conf.d/proxy_params.conf;
}
# 監(jiān)控金絲雀版本的錯(cuò)誤率
$ awk'$9 ~ /5../ && /127.0.0.1:8081/ {count++} END {print "Canary 5xx:", count}'/var/log/nginx/access.log
Canary 5xx: 12

$ awk'$9 ~ /5../ && /127.0.0.1:8080/ {count++} END {print "Stable 5xx:", count}'/var/log/nginx/access.log
Stable 5xx: 3

# 金絲雀錯(cuò)誤率略高,繼續(xù)觀察

限流與熔斷

在 upstream 壓力過大或響應(yīng)變慢時(shí),主動(dòng)拒絕部分請(qǐng)求,防止雪崩效應(yīng)。

# 限流配置
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=100r/s;
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;

server {
  location /api/ {
    # 令牌桶限流,burst=200 表示突發(fā)最多接受 200 個(gè)請(qǐng)求
    # nodelay 不延遲處理,直接返回 503
    limit_req zone=api_limit burst=200 nodelay;

    # 連接數(shù)限制
    limit_conn conn_limit 10;

    proxy_pass http://backend;
    proxy_next_upstream error timeout http_502 http_503;
  }
}

# 熔斷配置:基于響應(yīng)時(shí)間自動(dòng)降級(jí)
# 當(dāng) upstream 平均響應(yīng)時(shí)間超過閾值時(shí),返回降級(jí)響應(yīng)
proxy_cache_bypass $upstream_http_x_downgrade;

4.2 配置模板

生產(chǎn)環(huán)境完整配置示例

# /etc/nginx/nginx.conf
user nginx;
worker_processes auto;
worker_rlimit_nofile 65535;
error_log /var/log/nginx/error.log warn;
pid /run/nginx.pid;

events {
  worker_connections 65535;
  use epoll;
  multi_accept on;
}

http {
  include /etc/nginx/mime.types;
  default_type application/octet-stream;

  # 日志格式
  log_format main '$remote_addr - $remote_user [$time_local] "$request" '
          '$status $body_bytes_sent "$http_referer" '
          '"$http_user_agent" "$http_x_forwarded_for" '
          'rt=$request_time uct="$upstream_connect_time" '
          'uht="$upstream_header_time" urt="$upstream_response_time" '
          'request_id="$request_id"';

  access_log /var/log/nginx/access.log main buffer=16k flush=2s;

  # 基礎(chǔ)優(yōu)化
  sendfile on;
  tcp_nopush on;
  tcp_nodelay on;
  server_tokens off;

  # 超時(shí)配置
  keepalive_timeout 65;
  keepalive_requests 1000;
  client_header_timeout 15s;
  client_body_timeout 15s;
  send_timeout 60s;

  # 緩沖區(qū)配置
  client_max_body_size 100m;
  client_body_buffer_size 256k;
  client_header_buffer_size 4k;
  large_client_header_buffers 4 16k;

  # Gzip 壓縮
  gzip on;
  gzip_vary on;
  gzip_proxied any;
  gzip_comp_level 6;
  gzip_types text/plain text/css text/xml application/json application/javascript application/xml+rss application/rss+xml font/truetype font/opentype application/vnd.ms-fontobject image/svg+xml;

  # 隱藏 Nginx 版本號(hào)
  server_tokens off;

  # 安全頭
  add_header X-Frame-Options "SAMEORIGIN" always;
  add_header X-Content-Type-Options "nosniff" always;
  add_header X-XSS-Protection "1; mode=block" always;
  add_header Referrer-Policy "strict-origin-when-cross-origin" always;

  # upstream 塊定義
  include /etc/nginx/conf.d/upstream/*.conf;

  # 引入各站點(diǎn)的 server 配置
  include /etc/nginx/sites-enabled/*.conf;
}
# /etc/nginx/conf.d/upstream/backend.conf
upstream backend_php {
  least_conn;

  server 127.0.0.1:9000 weight=5 max_fails=3 fail_timeout=10s;
  server 127.0.0.1:9001 weight=5 max_fails=3 fail_timeout=10s;
  server 127.0.0.1:9002 backup;

  keepalive 32;
  keepalive_requests 1000;
  keepalive_timeout 60s;
}

upstream backend_static {
  server 127.0.0.1:8080 weight=5;
  server 127.0.0.1:8081 weight=5;
  server 127.0.0.1:8082 backup;

  keepalive 32;
}

upstream backend_api {
  ip_hash;

  server 10.0.1.20:8080;
  server 10.0.1.21:8080;
  server 10.0.1.22:8080;

  # 主動(dòng)健康檢查
  check interval=3000 rise=2 fall=2 timeout=1000 type=http;
  check_http_send "HEAD /health HTTP/1.0

";
  check_http_expect_alive http_2xx;
}
# /etc/nginx/sites-enabled/api.example.com.conf
server {
  listen 80;
  server_name api.example.com;

  # 將 HTTP 請(qǐng)求重定向到 HTTPS
  return 301 https://$server_name$request_uri;
}

server {
  listen 443 ssl http2;
  server_name api.example.com;

  ssl_certificate /etc/nginx/ssl/api.example.com.crt;
  ssl_certificate_key /etc/nginx/ssl/api.example.com.key;
  ssl_protocols TLSv1.2 TLSv1.3;
  ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
  ssl_prefer_server_ciphers off;
  ssl_session_cache shared10m;
  ssl_session_timeout 1d;
  ssl_session_tickets off;

  # 安全頭
  add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

  # 訪問日志
  access_log /var/log/nginx/api.example.com.access.log main buffer=16k;

  # 健康檢查端點(diǎn)(不經(jīng)過限流)
  location = /health {
    access_log off;
    return 200 "OK
";
    add_header Content-Type text/plain;
  }

  # API 路由
  location /api/v1/ {
    # 限流
    limit_req zone=api_limit burst=100 nodelay;
    limit_req_status 429;

    # proxy 配置
    proxy_pass http://backend_php;
    proxy_http_version 1.1;
    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_set_header Connection "";

    # 超時(shí)配置
    proxy_connect_timeout 10s;
    proxy_send_timeout 60s;
    proxy_read_timeout 120s;

    # 緩沖區(qū)配置
    proxy_buffering on;
    proxy_buffer_size 128k;
    proxy_buffers 8 256k;
    proxy_busy_buffer_size 256k;

    # 錯(cuò)誤處理:后端故障時(shí)返回降級(jí)響應(yīng)
    error_page 502 503 = @fallback;
  }

  # 靜態(tài)資源
  location /static/ {
    proxy_pass http://backend_static;
    proxy_cache static_cache;
    proxy_cache_valid 200 60m;
    proxy_cache_valid 404 1m;
    proxy_cache_use_stale error timeout updating;
    add_header X-Cache-Status $upstream_cache_status;
    expires 7d;
    add_header Cache-Control "public, immutable";
  }

  # 降級(jí)響應(yīng)
  location @fallback {
    default_type application/json;
    return 503 '{"code":503,"message":"Service temporarily unavailable","request_id":"$request_id"}';
  }

  # 429 Too Many Requests 響應(yīng)
  location = /429.html {
    internal;
    default_type application/json;
    return 429 '{"code":429,"message":"Rate limit exceeded","retry_after":1}';
  }
}

日志切割配置

# /etc/logrotate.d/nginx
/var/log/nginx/*.log{
  daily
  missingok
  rotate 30
  compress
  delaycompress
  notifempty
  create 0640 nginx adm
  sharedscripts
  postrotate
    [ -f /run/nginx.pid ] &&kill-USR1 $(cat /run/nginx.pid)
  endscript
}
# 手動(dòng)測(cè)試日志切割
$ logrotate -f /etc/logrotate.d/nginx
$ ls -la /var/log/nginx/
total 1234
-rw-r----- 1 nginx adm  45678 Apr 24 00:00 access.log
-rw-r----- 1 nginx adm  12345 Apr 24 00:00 access.log-20260424.gz
-rw-r----- 1 nginx adm  23456 Apr 24 00:00 error.log
-rw-r----- 1 nginx adm  8901 Apr 24 00:00 error.log-20260424.gz

性能測(cè)試基線

# 使用 wrk 進(jìn)行基準(zhǔn)性能測(cè)試
$ wrk -t4 -c100 -d60s --latency http://api.example.com/api/v1/health

Running 1mtest@ http://api.example.com/api/v1/health
 4 threads and 100 connections
 Thread Stats  Avg   Stdev   Max  +/- Stdev
  Latency   12.34ms  2.15ms 45.67ms  90.12%
  Req/Sec  2345.67   89.23 2500.00  85.00%
 Latency Distribution
  50%  11.89ms
  75%  13.45ms
  90%  15.23ms
  99%  25.67ms
 1234567 requestsin60.00s, 234.56MBread
Requests/sec: 20576.12
Transfer/sec:  3.91MB
# 使用 ab 進(jìn)行連接測(cè)試
$ ab -n 10000 -c 1000 -g ab_results.tsv http://api.example.com/api/v1/health

This is ApacheBench, Version 2.3 <$Revision: 1879490 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking api.example.com (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
Completed 7000 requests
Completed 8000 requests
Completed 9000 requests
Completed 10000 requests
Finished 10000 requests

Server Software:    nginx/1.26.2
Server Hostname:    api.example.com
Server Port:      443
SSL/TLS Protocol:    TLSv1.3, ECDHE-RSA-AES256-GCM-SHA384, 256bit

Document Path:     /api/v1/health
Document Length:    3 bytes

Concurrency Level:   1000
Time takenfortests:  12.345 seconds
Complete requests:   10000
Failed requests:    0
Non-2xx responses:   0
Total transferred:   2340000 bytes
HTML transferred:    30000 bytes
Requests per second:  810.23 [#/sec] (mean)
Time per request:    1234.567 [ms] (mean)
Time per request:    1.235 [ms] (mean, across all concurrent requests)
Transfer rate:     185.23 [Kbytes/sec] received

Connection Times (ms)
       min mean[+/-sd] median  max
Connect:    0  0  0.0   0    0
Processing:  123 456 78.9  434  1234
Waiting:    123 455 78.9  433  1233
Total:     123 456 78.9  434  1234

Percentage of the requests served within a certain time (ms)
 50%  434
 66%  456
 75%  478
 80%  489
 90%  534
 95%  612
 98%  723
 99%  789
100%  1234 (longest request)

4.3 故障應(yīng)急

502 故障的快速止血

故障發(fā)生時(shí),第一目標(biāo)是快速恢復(fù)服務(wù),最小化業(yè)務(wù)影響。

# 1. 立即檢查 error.log,確認(rèn) 502 根因類型
$ tail -100 /var/log/nginx/error.log | grep -E"[error]"| tail -20

# 2. 快速檢查后端服務(wù)狀態(tài)
$ systemctl status php-fpm node-backend gunicorn 2>&1 | grep -E"Active:|Main PID:"

# 3. 如果后端服務(wù)掛了,立即重啟
$ systemctl restart php-fpm
$ systemctl restart node-backend

# 4. 如果是單個(gè) upstream server 故障,臨時(shí)從 upstream 中移除
$ vim /etc/nginx/conf.d/upstream/backend.conf
# 注釋掉故障 server,保留可用的
upstream backend {
  server 127.0.0.1:9000;
 # server 127.0.0.1:9001; # 臨時(shí)禁用
}

$ nginx -t && nginx -s reload

# 5. 如果所有后端都不可用,啟動(dòng)備用服務(wù)
$ systemctl start emergency-backend

# 6. 擴(kuò)大上游超時(shí)時(shí)間,減少 502 觸發(fā)
$ sed -i's/proxy_read_timeout 120s;/proxy_read_timeout 300s;/'/etc/nginx/conf.d/upstream/*.conf
$ nginx -s reload

后端切換的手動(dòng)操作

# 手動(dòng)切換流量到備用后端
# 場(chǎng)景:主數(shù)據(jù)庫故障,需要切換到從庫

# 1. 備份當(dāng)前 upstream 配置
$ cp /etc/nginx/conf.d/upstream/app.conf /etc/nginx/conf.d/upstream/app.conf.bak.$(date +%Y%m%d%H%M%S)

# 2. 修改 upstream 指向備用后端
$ cat > /etc/nginx/conf.d/upstream/app_standby.conf <

業(yè)務(wù)降級(jí)方案

當(dāng)后端無法處理請(qǐng)求時(shí),返回預(yù)設(shè)的降級(jí)響應(yīng)而非 502,提升用戶體驗(yàn)。

# 降級(jí)配置示例
upstream backend_primary {
  server 127.0.0.1:8080;
  server 127.0.0.1:8081 backup;
}

# 主服務(wù)不可用時(shí)返回緩存或靜態(tài)降級(jí)內(nèi)容
proxy_cache_key "$host$request_uri";
proxy_cache_valid 200 10m;
proxy_cache_valid 404 1m;
proxy_cache_valid 500 502 503 504 1m;

location /api/ {
  # 嘗試主后端
  proxy_pass http://backend_primary;

  # 后端返回 502/503 時(shí)使用緩存
  proxy_cache_use_stale error timeout updating http_502 http_503 http_504;

  # 后端響應(yīng)慢時(shí)使用緩存
  proxy_cache_use_stale error timeout updating;

  # 緩存刷新時(shí)間
  proxy_cache_background_update on;
  proxy_cache_lock on;

  # 降級(jí)響應(yīng):如果緩存也沒有,返回靜態(tài) JSON
  error_page 502 503 504 = @degraded_response;
}

location @degraded_response {
  default_type application/json;
  # 返回最近緩存的響應(yīng)(由 proxy_cache_valid 控制)
  add_header X-Cache-Status "DEGRADED";
  return 200 '{"code":200,"message":"Cached response","data":null,"degraded":true}';
}

五、擴(kuò)展閱讀與證據(jù)鏈

5.1 官方文檔

Nginx 官方文檔

Nginx 官方文檔(英文):https://nginx.org/en/docs/

Nginx upstream 模塊文檔:https://nginx.org/en/docs/http/ngx_http_upstream_module.html

Nginx proxy 模塊文檔:https://nginx.org/en/docs/http/ngx_http_proxy_module.html

Nginx 故障排查指南:https://nginx.org/en/docs/support.html

PHP-FPM 官方文檔

PHP-FPM 配置說明:https://www.php.net/manual/en/install.fpm.configuration.php

PHP-FPM 進(jìn)程管理:https://www.php.net/manual/en/install.fpm.pm.php

第三方模塊文檔

nginx_upstream_check_module(阿里巴巴):https://github.com/yaoweibin/nginx_upstream_check_module

OpenResty + lua-upstream:https://github.com/openresty/lua-upstream-nginx-module

5.2 關(guān)鍵配置文件參考

nginx.conf 完整模板

# Nginx 1.26.x / 1.27.x 完整配置模板
user nginx;
worker_processes auto;
worker_rlimit_nofile 65535;
worker_rlimit_sigpending 65535;

error_log /var/log/nginx/error.log warn;
pid /run/nginx.pid;

events {
  worker_connections 65535;
  use epoll;
  multi_accept on;
  accept_mutex on;
  accept_mutex_delay 500ms;
}

http {
  include /etc/nginx/mime.types;
  default_type application/octet-stream;

  # 字符集
  charset utf-8;
  charset_types text/plain text/css text/xml text/javascript application/javascript application/json application/xml;

  # 日志格式(包含 upstream 詳細(xì)信息)
  log_format main_ext '$remote_addr - $remote_user [$time_local] "$request" '
            '$status $body_bytes_sent "$http_referer" '
            '"$http_user_agent" "$http_x_forwarded_for" '
            'rt=$request_time '
            'uct="$upstream_connect_time" '
            'uht="$upstream_header_time" '
            'urt="$upstream_response_time" '
            'request_id="$request_id" '
            'upstream_addr="$upstream_addr" '
            'upstream_status="$upstream_status"';

  access_log /var/log/nginx/access.log main_ext buffer=32k flush=5s;

  # 基礎(chǔ)優(yōu)化
  sendfile on;
  tcp_nopush on;
  tcp_nodelay on;

  # 超時(shí)配置
  keepalive_timeout 65;
  keepalive_requests 1000;
  client_header_timeout 15s;
  client_body_timeout 15s;
  send_timeout 60s;
  lingering_timeout 5s;
  reset_timedout_connection on;

  # 緩沖區(qū)配置
  client_max_body_size 100m;
  client_body_buffer_size 256k;
  client_header_buffer_size 4k;
  large_client_header_buffers 4 32k;
  connection_pool_size 256;
  request_pool_size 4k;

  # Gzip 壓縮
  gzip on;
  gzip_vary on;
  gzip_proxied any;
  gzip_comp_level 6;
  gzip_min_length 1024;
  gzip_types text/plain text/css text/xml application/json application/javascript application/xml application/atom+xml application/rss+xml image/svg+xml;

  # 安全配置
  server_tokens off;
  hide_server_token on;

  # Open file cache
  open_file_cache max=65535 inactive=60s;
  open_file_cache_valid 30s;
  open_file_cache_min_uses 2;
  open_file_cache_errors on;

  # 限制請(qǐng)求
  limit_req_zone $binary_remote_addr zone=general:10m rate=100r/s;
  limit_req_zone $binary_remote_addr zone=api:10m rate=1000r/s;
  limit_conn_zone $binary_remote_addr zone=conn:10m;

  # 引入 upstream 配置
  include /etc/nginx/conf.d/upstream/*.conf;

  # 引入站點(diǎn)配置
  include /etc/nginx/sites-enabled/*.conf;
}

PHP-FPM 配置參數(shù)說明

; /etc/php-fpm/www.conf 關(guān)鍵參數(shù)說明

; 進(jìn)程管理器類型
; static - 固定數(shù)量的子進(jìn)程
; dynamic - 動(dòng)態(tài)數(shù)量的子進(jìn)程
; ondemand - 按需創(chuàng)建子進(jìn)程
pm = dynamic

; 子進(jìn)程最大數(shù)量
pm.max_children = 50

; 啟動(dòng)時(shí)創(chuàng)建的子進(jìn)程數(shù)(dynamic 模式)
pm.start_servers = 10

; 最小空閑子進(jìn)程數(shù)(dynamic 模式)
pm.min_spare_servers = 5

; 最大空閑子進(jìn)程數(shù)(dynamic 模式)
pm.max_spare_servers = 20

; 子進(jìn)程處理請(qǐng)求數(shù)上限,達(dá)到后重啟(防止內(nèi)存泄漏累積)
pm.max_requests = 500

; 子進(jìn)程空閑超時(shí)
pm.process_idle_timeout = 10s

; 緊急重啟閾值
emergency_restart_threshold = 10
emergency_restart_interval = 1m

; 進(jìn)程控制超時(shí)(處理 SIGTERM 需要的時(shí)間)
process_control_timeout = 10s

; PHP 內(nèi)存限制
php_admin_value[memory_limit] = 256M
php_admin_flag[log_errors] = on

; 慢查詢?nèi)罩?slowlog = /var/log/php-fpm/www-slow.log
request_slowlog_timeout = 10s
request_slowlog_trace_depth = 20

; 健康檢查
ping.path = /ping
ping.response = pong

; Socket 配置
listen = /var/run/php-fpm/www.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660

systemd Service 文件

; /etc/systemd/system/php-fpm.service
[Unit]
Description=PHP FastCGI Process Manager
Documentation=man:php-fpm(8)
After=network.target

[Service]
Type=notify
PIDFile=/run/php-fpm/php-fpm.pid
ExecStart=/usr/sbin/php-fpm --nodaemonize --fpm-config /etc/php-fpm.conf
ExecReload=/bin/kill -USR2 $MAINPID
ExecStop=/bin/kill -SIGINT $MAINPID
PrivateTmp=true
Restart=always
RestartSec=10s
TimeoutStartSec=30s
TimeoutStopSec=30s

; 資源限制
LimitNOFILE=65535
LimitNPROC=8192

; OOM 策略 - 不阻止 OOM Killer
OOMScoreAdjust=-500

[Install]
WantedBy=multi-user.target
; /etc/systemd/system/nginx.service
[Unit]
Description=nginx - high performance web server
Documentation=https://nginx.org/en/docs/
After=network.target remote-fs.target nss-lookup.target

[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t -c /etc/nginx/nginx.conf
ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
PrivateTmp=true
Restart=always
RestartSec=5s

; 資源限制
LimitNOFILE=65535
LimitCORE=infinity

[Install]
WantedBy=multi-user.target

5.3 常見錯(cuò)誤碼速查表

errno 系統(tǒng)調(diào)用錯(cuò)誤 含義 常見場(chǎng)景
111 ECONNREFUSED 連接被拒絕 upstream 端口未監(jiān)聽
110 ETIMEDOUT 連接超時(shí) upstream 無響應(yīng),防火墻攔截
113 EHOSTUNREACH 主機(jī)不可達(dá) IP 地址錯(cuò)誤,網(wǎng)絡(luò)不通
111 ECONNREFUSED 連接被拒絕 PHP-FPM socket 權(quán)限錯(cuò)誤
104 ECONNRESET 連接被重置 upstream 進(jìn)程崩潰
32 EPIPE 管道破裂 upstream 提前關(guān)閉連接
2 ENOENT 文件不存在 Unix socket 文件不存在

5.4 502 排查流程圖(文字版)

發(fā)現(xiàn) 502 錯(cuò)誤
  |
  v
檢查 error.log 中的具體錯(cuò)誤信息
  |
  +--->"connect() failed (111)"---> upstream 端口未監(jiān)聽
  |   |
  |   +---> 檢查后端服務(wù)是否運(yùn)行: systemctl status php-fpm/node-backend
  |   +---> 檢查端口/socket 是否監(jiān)聽: ss -tlnp | grep 9000
  |   +---> 檢查配置中 IP:端口是否正確
  |
  +--->"upstream prematurely closed"---> upstream 進(jìn)程崩潰
  |   |
  |   +---> 檢查 dmesg | grep -i oom(內(nèi)存不足)
  |   +---> 檢查后端錯(cuò)誤日志(PHP fatal error、core dump)
  |   +---> 檢查 upstream 是否被 OOM Killer 殺死
  |
  +--->"upstream timed out"---> 后端處理超時(shí)
  |   |
  |   +---> 檢查后端處理時(shí)間(數(shù)據(jù)庫查詢、外部 API)
  |   +---> 調(diào)整 proxy_read_timeout
  |   +---> 優(yōu)化后端性能或增加資源
  |
  +--->"no live upstreams"---> 所有 upstream 都不可用
     |
     +---> 檢查所有 upstream server 的健康狀態(tài)
     +---> 可能是 max_fails 導(dǎo)致所有節(jié)點(diǎn)被暫時(shí)禁用
     +-----> 等待 fail_timeout 過去或重啟 upstream

六、自檢清單

6.1 部署前檢查清單

[ ] Nginx 配置文件語法驗(yàn)證通過:nginx -t

[ ] 后端服務(wù)已啟動(dòng)并監(jiān)聽正確端口

[ ] upstream 配置的 IP:端口與實(shí)際一致

[ ] 超時(shí)參數(shù)(proxy_connect_timeout、proxy_read_timeout)已根據(jù)業(yè)務(wù)調(diào)整

[ ] 緩沖區(qū)參數(shù)(proxy_buffer_size、proxy_buffers)已配置

[ ] keepalive 配置已啟用(proxy_http_version 1.1 + Connection "")

[ ] socket 文件權(quán)限正確(listen.owner/listen.group)

[ ] SELinux/AppArmor 策略允許 Nginx 與后端通信

[ ] 日志級(jí)別設(shè)置為 warn 或 error

[ ] 健康檢查已配置(被動(dòng)或主動(dòng))

6.2 故障發(fā)生時(shí)的快速檢查項(xiàng)

[ ] 查看 error.log,確認(rèn)具體錯(cuò)誤信息

[ ] 確認(rèn)后端服務(wù)進(jìn)程存活:systemctl status php-fpm

[ ] 確認(rèn)端口/socket 監(jiān)聽:ss -tlnp | grep 9000

[ ] 測(cè)試后端可連接性:curl -v http://127.0.0.1:9000/health

[ ] 檢查系統(tǒng)資源(CPU、內(nèi)存、磁盤IO)

[ ] 檢查 dmesg 中是否有 OOM Killer 記錄

[ ] 檢查 upstream 是否被標(biāo)記為 down

6.3 復(fù)盤與預(yù)防檢查項(xiàng)

[ ] 錯(cuò)誤是否可復(fù)現(xiàn)

[ ] 根因是否已定位并解決

[ ] 是否有監(jiān)控告警覆蓋同類問題

[ ] 是否需要調(diào)整超時(shí)/緩沖區(qū)等參數(shù)

[ ] 是否需要增加資源或優(yōu)化架構(gòu)

[ ] 是否更新了 SOP 和運(yùn)維文檔

附錄 A:錯(cuò)誤日志關(guān)鍵字索引

關(guān)鍵字 根因 處理優(yōu)先級(jí)
connect() failed (111) upstream 未監(jiān)聽端口 P0 - 立即處理
upstream prematurely closed upstream 崩潰 P0 - 立即處理
upstream timed out 后端響應(yīng)超時(shí) P1 - 優(yōu)化超時(shí)
no live upstreams 所有 upstream 不可用 P0 - 立即處理
buffer is too small 緩沖區(qū)配置不足 P1 - 調(diào)整緩沖區(qū)
Permission denied 權(quán)限問題 P0 - 立即處理
connection reset upstream 強(qiáng)制斷開 P1 - 檢查 upstream 健康
broken header upstream 返回?fù)p壞響應(yīng) P1 - 檢查 upstream

附錄 B:命令速查卡片

# Nginx 基礎(chǔ)操作
nginx -t          # 測(cè)試配置語法
nginx -s reload      # 優(yōu)雅重載配置
nginx -s stop       # 快速關(guān)閉
nginx -s quit       # 優(yōu)雅關(guān)閉
nginx -V         # 查看版本和編譯參數(shù)

# 日志分析
tail -f /var/log/nginx/error.log | grep 502
awk'$9==502 {count++} END {print count}'/var/log/nginx/access.log
grep -C 5"502"/var/log/nginx/error.log

# 后端服務(wù)檢查
systemctl status php-fpm
ss -tlnp | grep -E':(80|443|9000)'
ps aux | grep php-fpm
netstat -ant | grep :8080 | wc -l

# 健康檢查
curl -v http://127.0.0.1:8080/health
SCRIPT_NAME=/ping cgi-fcgi -bind-connect /var/run/php-fpm/www.sock
nc -zv 127.0.0.1 9000 -w 3

# 性能監(jiān)控
ss -s             # 連接統(tǒng)計(jì)
top -b -n 1 | head -20    # 系統(tǒng)資源
nginx -s reopen       # 重新打開日志文件(配合 logrotate)

附錄 C:配置參數(shù)參考表

upstream 指令

指令 默認(rèn)值 說明
server - 定義 upstream server,格式:address [parameters]
weight 1 權(quán)重,用于加權(quán)輪詢
max_fails 1 失敗次數(shù)閾值,超過后標(biāo)記為不可用
fail_timeout 10s 失敗超時(shí)時(shí)間,同時(shí)也是不可用持續(xù)時(shí)間
backup - 標(biāo)記為備用服務(wù)器
down - 標(biāo)記為永久不可用
keepalive - keepalive 連接池大小
keepalive_requests 1000 單連接最大請(qǐng)求數(shù)
keepalive_timeout 60s keepalive 空閑超時(shí)
slow_start 0 慢啟動(dòng)時(shí)間(商業(yè)版 Nginx Plus)

proxy 指令

指令 默認(rèn)值 說明
proxy_pass - 指定 upstream 或 URL
proxy_http_version 1.0 HTTP 版本
proxy_connect_timeout 60s 連接超時(shí)
proxy_send_timeout 60s 發(fā)送請(qǐng)求超時(shí)
proxy_read_timeout 60s 讀取響應(yīng)超時(shí)
proxy_buffer_size 4k/8k 響應(yīng)頭緩沖區(qū)
proxy_buffers 8 4k/8k 響應(yīng)體緩沖區(qū)
proxy_busy_buffer_size proxy_buffer_size 忙碌緩沖區(qū)
proxy_buffering on 是否啟用緩沖
proxy_max_temp_file_size 1024m 臨時(shí)文件總大小
proxy_temp_file_write_size proxy_buffer_size 單次寫入臨時(shí)文件大小
proxy_set_header Host $proxy_host 設(shè)置請(qǐng)求頭
proxy_next_upstream error timeout 故障轉(zhuǎn)移條件

本文檔由運(yùn)維團(tuán)隊(duì)基于多年生產(chǎn)環(huán)境排障經(jīng)驗(yàn)整理,涵蓋 Nginx 502 錯(cuò)誤的識(shí)別、診斷、處理的完整方法論。如有補(bǔ)充或修正,請(qǐng)?zhí)峤?PR 至內(nèi)部文檔倉庫。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • Linux
    +關(guān)注

    關(guān)注

    88

    文章

    11825

    瀏覽量

    219616
  • 服務(wù)器
    +關(guān)注

    關(guān)注

    14

    文章

    10377

    瀏覽量

    91777
  • nginx
    +關(guān)注

    關(guān)注

    0

    文章

    196

    瀏覽量

    13224

原文標(biāo)題:Nginx 502 Bad Gateway:從日志里挖出深藏的配置坑

文章出處:【微信號(hào):magedu-Linux,微信公眾號(hào):馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    nginx重啟命令linux步驟是什么?

      1、驗(yàn)證nginx配置文件是否正確   方法一:進(jìn)入nginx安裝目錄sbin下,輸入命令./nginx -t   看到如下顯示nginx
    發(fā)表于 07-11 17:13

    nginx錯(cuò)誤頁面配置

    16、nginx 錯(cuò)誤頁面配置nginx錯(cuò)誤頁面包括404 403 500 502 503 504等頁面,只需要在server中增加以下配置
    發(fā)表于 07-26 06:54

    電瓶壞損成因、修復(fù)與保養(yǎng)方法!

    電瓶壞損成因、修復(fù)與保養(yǎng)方法!
    發(fā)表于 11-09 17:38 ?1323次閱讀

    電感嘯叫的成因與解決方法

    電子專業(yè)單片機(jī)相關(guān)知識(shí)學(xué)習(xí)教材資料——電感嘯叫的成因與解決方法
    發(fā)表于 10-10 14:17 ?0次下載

    分享nginx 502的解決方法

    還好,我印象中多年前遇到過一次類似的問題,不過是linux代理linux,癥狀和該問題基本類似,當(dāng)時(shí)的解決辦法是,修改被代理的linux服務(wù)器nginx配置文件nginx.conf中worker_connections參數(shù)的值,當(dāng)時(shí)記得是51200,改為4096就ok了。
    的頭像 發(fā)表于 02-09 08:37 ?7308次閱讀

    PHP出現(xiàn)502錯(cuò)誤的問題如何解決詳細(xì)資料說明

    本文檔的主要內(nèi)容詳細(xì)介紹的是PHP出現(xiàn)502錯(cuò)誤的問題如何解決詳細(xì)資料說明
    發(fā)表于 03-14 17:17 ?6次下載
    PHP出現(xiàn)<b class='flag-5'>502</b><b class='flag-5'>錯(cuò)誤</b>的問題如何解決詳細(xì)資料說明

    科普系列:CAN總線錯(cuò)誤幀及排查方法簡(jiǎn)介

    作者|蒹葭小編|吃不飽CAN幀有多種格式,錯(cuò)誤幀作為CAN幀中獨(dú)特的一種,了解其作用,類型與產(chǎn)生原因,對(duì)于進(jìn)行測(cè)試以及開發(fā)有很大的幫助,本文將對(duì)錯(cuò)誤幀的相關(guān)基礎(chǔ)知識(shí)以及后續(xù)的分析排查進(jìn)行介紹。01
    的頭像 發(fā)表于 02-23 15:11 ?5510次閱讀
    科普系列:CAN總線<b class='flag-5'>錯(cuò)誤</b>幀及<b class='flag-5'>排查</b><b class='flag-5'>方法</b>簡(jiǎn)介

    如何用示波器排查CAN的各種錯(cuò)誤幀呢?

    如何用示波器排查CAN的各種錯(cuò)誤幀呢? 導(dǎo)言: 控制器局域網(wǎng)絡(luò)(Controller Area Network,CAN)是一種常用的現(xiàn)場(chǎng)總線通信協(xié)議,廣泛應(yīng)用于汽車電子系統(tǒng)、工業(yè)自動(dòng)化等領(lǐng)域。然而
    的頭像 發(fā)表于 12-07 11:09 ?2455次閱讀

    玩轉(zhuǎn)Nginx日志管理:高效排查問題的終極指南

    Nginx日志對(duì)于統(tǒng)計(jì)、系統(tǒng)服務(wù)排錯(cuò)很有用。Nginx日志主要分為兩種:access_log(訪問日志)和error_log(錯(cuò)誤日志)。通過訪問日志我們可以得到用戶的IP地址、瀏覽器的信息,請(qǐng)求
    的頭像 發(fā)表于 12-30 13:50 ?1442次閱讀

    云原生環(huán)境里Nginx的故障排查思路

    本文聚焦于云原生環(huán)境下Nginx的故障排查思路。隨著云原生技術(shù)的廣泛應(yīng)用,Nginx作為常用的高性能Web服務(wù)器和反向代理服務(wù)器,在容器化和編排的環(huán)境中面臨著新的故障場(chǎng)景和挑戰(zhàn)。
    的頭像 發(fā)表于 06-17 13:53 ?1191次閱讀
    云原生環(huán)境里<b class='flag-5'>Nginx</b>的故障<b class='flag-5'>排查</b>思路

    電商API常見錯(cuò)誤排查指南:避免集成陷阱

    ? 在電商平臺(tái)開發(fā)中,API集成是連接系統(tǒng)、實(shí)現(xiàn)數(shù)據(jù)交換的核心環(huán)節(jié)。然而,許多開發(fā)者在集成過程中常遇到錯(cuò)誤,導(dǎo)致項(xiàng)目延遲、數(shù)據(jù)丟失或用戶體驗(yàn)下降。本文將逐步介紹常見錯(cuò)誤類型、排查方法
    的頭像 發(fā)表于 07-11 14:21 ?2324次閱讀
    電商API常見<b class='flag-5'>錯(cuò)誤</b><b class='flag-5'>排查</b>指南:避免集成陷阱

    Nginx常見故障案例總結(jié)

    在互聯(lián)網(wǎng)公司的運(yùn)維生涯中,Nginx故障可以說是最常見也最讓人頭疼的問題之一。從簡(jiǎn)單的配置錯(cuò)誤到復(fù)雜的性能瓶頸,從偶發(fā)的502到持續(xù)的高延遲,每一個(gè)故障背后都有其獨(dú)特的原因和解決方案。
    的頭像 發(fā)表于 09-18 14:51 ?1546次閱讀

    Nginx常見故障排查手冊(cè)

    Nginx 報(bào) 502、504、連接超時(shí),看起來都是“請(qǐng)求沒成功”,但根因完全不是一類問題。502 更多是上游服務(wù)直接返回?zé)o效響應(yīng)、連接被拒絕或進(jìn)程掛了;504 更像是請(qǐng)求已經(jīng)到上游,但超時(shí)窗口內(nèi)沒
    的頭像 發(fā)表于 03-11 09:47 ?476次閱讀

    MySQL磁盤空間問題的成因排查方法

    運(yùn)維工程師經(jīng)常會(huì)遇到這樣的場(chǎng)景:MySQL 服務(wù)器的磁盤空間告警,但查看數(shù)據(jù)目錄時(shí)發(fā)現(xiàn)數(shù)據(jù)庫本身并不大。大量磁盤空間被未知文件消耗。通過排查發(fā)現(xiàn),二進(jìn)制日志(Binary Log)是主要的磁盤空間消耗者。
    的頭像 發(fā)表于 04-13 13:57 ?159次閱讀

    Nginx日志分析命令實(shí)踐和常見問題排查思路

    日常運(yùn)維工作中,日志分析是排查問題最直接的手段。Nginx 作為入口層代理,幾乎所有請(qǐng)求都要經(jīng)過它。當(dāng)網(wǎng)站出現(xiàn)響應(yīng)慢、500 錯(cuò)誤502 網(wǎng)關(guān)超時(shí)、限流失效等問題時(shí),第一反應(yīng)應(yīng)該是查
    的頭像 發(fā)表于 04-15 14:12 ?261次閱讀
    甘肃省| 黎城县| 亳州市| 鹤壁市| 阿拉善右旗| 五指山市| 桂阳县| 高邮市| 云南省| 光山县| 余干县| 乐山市| 合作市| 梁平县| 阜新市| 建昌县| 河南省| 田阳县| 尚义县| 佛学| 古田县| 增城市| 四子王旗| 南部县| 沙河市| 米易县| 大方县| 涞源县| 辰溪县| 茌平县| 秀山| 灵武市| 喜德县| 元氏县| 衡南县| 那曲县| 同仁县| 五华县| 宜昌市| 喀喇沁旗| 徐水县|