引言:狀態(tài)碼不是數(shù)字游戲
作為運(yùn)維工程師,每天都要和 502、503、504 這些狀態(tài)碼打交道。但真正能說清楚這三者區(qū)別的人并不多——很多人只知道"網(wǎng)關(guān)錯誤",卻不清楚具體是哪個環(huán)節(jié)出了問題。
這篇文章從 HTTP 協(xié)議原理講起,詳細(xì)區(qū)分這三種狀態(tài)碼的觸發(fā)場景、排查方法,并給出實(shí)際的排障案例??赐曛螅阌龅竭@類問題應(yīng)該能快速定位根因。
前置知識:HTTP 協(xié)議基礎(chǔ)、Nginx/Apache 基礎(chǔ)
實(shí)驗(yàn)環(huán)境:CentOS Stream 9 / Ubuntu 24.04 LTS
1 HTTP 狀態(tài)碼體系
1.1 HTTP 狀態(tài)碼分類
HTTP 狀態(tài)碼結(jié)構(gòu): 1xx - 信息響應(yīng) 2xx - 成功響應(yīng) 3xx - 重定向 4xx - 客戶端錯誤 5xx - 服務(wù)器錯誤 重點(diǎn)關(guān)注 5xx: 502 Bad Gateway 503 Service Unavailable 504 Gateway Timeout
1.2 5xx 狀態(tài)的共同點(diǎn)
# Nginx 配置:返回 5xx 狀態(tài)碼時記錄詳細(xì)日志 log_format detailed '$remote_addr - $remote_user [$time_local] ' '"$request" $status $body_bytes_sent ' '"$http_referer" "$http_user_agent" ' 'rt=$request_time uct="$upstream_connect_time" ' 'uht="$upstream_header_time" urt="$upstream_response_time"'; access_log /var/log/nginx/detailed.log detailed; # 自定義錯誤頁面 error_page 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; internal; }
1.3 錯誤碼與 HTTP 協(xié)議層的關(guān)系
┌─────────────────────────────────────┐
│ HTTP 層(應(yīng)用層) │
│ 理解請求內(nèi)容、狀態(tài)碼、緩存控制等 │
└─────────────────────────────────────┘
▲
│ 協(xié)議解析
│
┌─────────────────────────────────────┴───────────────────────────┐
│ Proxy/網(wǎng)關(guān) 層 │
│ Nginx 作為反向代理,接收客戶端請求,轉(zhuǎn)發(fā)給后端 │
│ Nginx 負(fù)責(zé)返回 502/503/504 狀態(tài)碼 │
└─────────────────────────────────────────────────────────────────┘
▲
│ 轉(zhuǎn)發(fā)請求
│
┌─────────────────────────────────────┴───────────────────────────┐
│ Upstream(后端服務(wù))層 │
│ PHP-FPM、Node.js、Python uWSGI、Java Tomcat 等 │
│ 后端服務(wù)可能返回 500 錯誤或其他狀態(tài) │
└─────────────────────────────────────────────────────────────────┘
2 502 Bad Gateway 深度解析
2.1 502 的定義
502 Bad Gateway:作為網(wǎng)關(guān)或代理的服務(wù)器收到了無效響應(yīng)。
客戶端 Nginx PHP-FPM | | | | ──────── GET / ──────> | | | | ──────── FastCGI ──────> | | | | | | <─────── (無響應(yīng)) ─────── | ? | ? ? ? ? ? ? ? ? ? ? ? ? | ? ? ?連接被拒絕/超時 ? ? ? | ? | ? ? ? ? ? ? ? ? ? ? ? ? | ? ? ? ? ? ? ? ? ? ? ? ? ? | ? | <──── 502 Bad Gateway -| ? ? ? ? ? ? ? ? ? ? ? ? ? | ? | ? ? ? ? ? ? ? ? ? ? ? ? | ? ? ? ? ? ? ? ? ? ? ? ? ? |
2.2 502 的典型觸發(fā)場景
場景一:后端服務(wù)未啟動
# 檢查 PHP-FPM 是否運(yùn)行 systemctl status php-fpm # 或 ps aux | grep php-fpm # 如果未運(yùn)行 sudo systemctl start php-fpm sudo systemctlenablephp-fpm
場景二:后端端口配置錯誤
# Nginx 配置
upstream backend {
server 127.0.0.1:9000; # 正確的端口
# server 127.0.0.1:9001; # 錯誤的端口(服務(wù)未監(jiān)聽)
}
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# FastCGI 配置(PHP)
location ~ .php$ {
fastcgi_pass 127.0.0.1:9000; # 檢查端口是否正確
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
場景三:后端服務(wù)崩潰
# 查看 PHP-FPM 錯誤日志 tail -100 /var/log/php-fpm/error.log # 或 journalctl -u php-fpm -n 100 --no-pager # 查看進(jìn)程狀態(tài) ps aux | grep php-fpm # 如果進(jìn)程存在但無法響應(yīng),可能是 worker 進(jìn)程耗盡
場景四:連接數(shù)耗盡
# PHP-FPM 配置檢查 cat /etc/php-fpm.d/www.conf | grep -E"^pm|^pm.|^request_" # 典型配置 [www] pm = dynamic pm.max_children = 50 # 最大子進(jìn)程數(shù) pm.start_servers = 5 # 啟動時進(jìn)程數(shù) pm.min_spare_servers = 5# 最小空閑進(jìn)程 pm.max_spare_servers = 35# 最大空閑進(jìn)程 pm.max_requests = 500 # 每個進(jìn)程處理多少請求后回收 # 如果 max_children 已滿,新請求會排隊(duì)或超時
2.3 502 排查流程圖
502 錯誤發(fā)生
│
├── Step 1: 檢查 Nginx 能否連接后端
│ ├── telnet 127.0.0.1 9000
│ ├── nc -zv 127.0.0.1 9000
│ └── ss -tlnp | grep 9000
│
├── Step 2: 檢查后端服務(wù)狀態(tài)
│ ├── systemctl status php-fpm
│ ├── ps aux | grep php-fpm
│ └── ss -tlnp | grep :9000
│
├── Step 3: 檢查后端資源
│ ├── /var/log/php-fpm/error.log
│ ├── dmesg | tail
│ └── free -h
│
└── Step 4: 檢查 Nginx 日志
├── /var/log/nginx/error.log
└── /var/log/nginx/access.log (rt 字段)
2.4 502 實(shí)際排查腳本
#!/bin/bash # check_502.sh - 502 錯誤快速排查 echo"==========================================" echo" 502 錯誤排查" echo"==========================================" # 1. 檢查 Nginx 狀態(tài) echo"" echo"[1] Nginx 服務(wù)狀態(tài)" systemctl is-active nginx &&echo"? Nginx 運(yùn)行中"||echo"? Nginx 未運(yùn)行" ss -tlnp | grep :80 | head -5 # 2. 檢查后端服務(wù) echo"" echo"[2] PHP-FPM 服務(wù)狀態(tài)" systemctl is-active php-fpm &&echo"? PHP-FPM 運(yùn)行中"||echo"? PHP-FPM 未運(yùn)行" ps aux | grep -E"php-fpm|php-cgi"| grep -v grep | head -5 # 3. 檢查端口監(jiān)聽 echo"" echo"[3] 端口監(jiān)聽狀態(tài)" ss -tlnp | grep -E":80|:9000|:9001|:8080"| head -10 # 4. 檢查連接測試 echo"" echo"[4] 后端連接測試" timeout 3 bash -c"echo > /dev/tcp/127.0.0.1/9000"2>/dev/null &&echo"? 127.0.0.1:9000 可連接"||echo"? 127.0.0.1:9000 無法連接" timeout 3 bash -c"echo > /dev/tcp/127.0.0.1/9001"2>/dev/null &&echo"? 127.0.0.1:9001 可連接"||echo"? 127.0.0.1:9001 無法連接" # 5. 檢查資源使用 echo"" echo"[5] 資源使用情況" free -h | grep Mem df -h / | tail -1 # 6. 查看 Nginx 錯誤日志 echo"" echo"[6] Nginx 502 錯誤日志(最近 10 條)" grep -A2"502"/var/log/nginx/error.log 2>/dev/null | tail -20 # 7. 查看 PHP-FPM 錯誤日志 echo"" echo"[7] PHP-FPM 錯誤日志(最近 10 條)" tail -10 /var/log/php-fpm/error.log 2>/dev/null || tail -10 /var/log/php-fpm/www-error.log 2>/dev/null echo"" echo"==========================================" echo" 排查完成" echo"=========================================="
3 503 Service Unavailable 深度解析
3.1 503 的定義
503 Service Unavailable:服務(wù)器暫時無法處理請求,可能是過載或維護(hù)。
客戶端 Nginx 后端服務(wù) | | | | ──────── GET / ──────> | | | | | | | <─────── 503 ────────── ? | ? | ? ? ? ? ? ? ? ? ? ? ? ? | ? 服務(wù)暫時不可用 ? ? ? ? ? | ? | ? ? ? ? ? ? ? ? ? ? ? ? | ? ? ? ? ? ? ? ? ? ? ? ? ? | ? | <──── 503 Service ----- | ? ? ? ? ? ? ? ? ? ? ? ? ? | ? | ? ? ? ? Unavailable ? ? ?| ? ? ? ? ? ? ? ? ? ? ? ? ? | ? | ? ? ? ? ? ? ? ? ? ? ? ? | ? ? ? ? ? ? ? ? ? ? ? ? ? |
3.2 503 的典型觸發(fā)場景
場景一:后端服務(wù)主動返回 503
# Nginx 配置:限流觸發(fā) 503
limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s;
server {
listen 80;
server_name example.com;
location / {
limit_req zone=one burst=20 nodelay;
proxy_pass http://backend;
}
}
# 自定義 503 頁面
error_page 503 /503.html;
location = /503.html {
root /usr/share/nginx/html;
internal;
}
場景二:維護(hù)模式
# 維護(hù)開關(guān)
set $maintenance false;
# 可以通過變量控制
if (-f /var/www/maintenance.html) {
set $maintenance true;
}
server {
listen 80;
server_name example.com;
if ($maintenance = true) {
return 503;
}
location / {
proxy_pass http://backend;
}
error_page 503 @maintenance;
location @maintenance {
root /var/www;
rewrite ^(.*)$ /maintenance.html break;
}
}
場景三:連接數(shù)限制
# Nginx 層面限制
limit_conn_zone $binary_remote_addr zone=addr:10m;
server {
listen 80;
location / {
limit_conn addr 10; # 每個 IP 最多 10 個連接
proxy_pass http://backend;
}
}
場景四:后端服務(wù)過載
# 查看當(dāng)前連接數(shù) ss -ant | grep :8080 | wc -l # 查看 PHP-FPM 狀態(tài)頁面 # 需要啟用 status 頁面 cat /etc/php-fpm.d/www.conf | grep status # pm.status_path = /status # Nginx 配置 status 頁面 location ~ ^/(status|ping)$ { access_log off; allow 127.0.0.1; deny all; fastcgi_pass 127.0.0.1:9000; fastcgi_param SCRIPT_FILENAME$document_root$fastcgi_script_name; include fastcgi_params; } # 訪問狀態(tài)頁面 curl http://127.0.0.1/status # pool: www # process manager: dynamic # status: idle # accepted conn: 12345 # listen queue: 0 # max listen queue: 10 # listen queue len: 10 # idle processes: 4 # active processes: 1 # total processes: 5 # max children reached: 0
3.3 503 與限流的配合
#!/bin/bash
# test_nginx_limit.sh - 測試 Nginx 限流效果
echo"測試 Nginx 限流配置..."
echo""
# 使用 ab 進(jìn)行壓力測試
# 安裝 ab(如果未安裝)
whichab || sudo dnf install httpd-tools -y
# 單個請求測試
echo"=== 正常請求測試 ==="
curl -I http://localhost/ 2>/dev/null | head -1
# 并發(fā)測試
echo""
echo"=== 限流測試(20 并發(fā),50 請求)==="
ab -n 50 -c 20 http://localhost/
# 查看限流日志
echo""
echo"=== Nginx 限流日志 ==="
tail -20 /var/log/nginx/error.log | grep -ilimit||echo"無限流日志"
# 查看響應(yīng)碼統(tǒng)計(jì)
echo""
echo"=== 響應(yīng)碼統(tǒng)計(jì) ==="
awk'{print $9}'/var/log/nginx/access.log | sort | uniq -c | sort -rn
3.4 503 排查流程圖
503 錯誤發(fā)生
│
├── Step 1: 判斷是 Nginx 返回還是后端返回
│ ├── 查看響應(yīng)頭
│ └── curl -I http://example.com
│
├── Step 2: 如果是 Nginx 返回
│ ├── 檢查限流配置 (limit_req)
│ ├── 檢查連接數(shù)限制 (limit_conn)
│ └── 檢查維護(hù)模式
│
└── Step 3: 如果是后端返回
├── 檢查后端服務(wù)是否過載
├── 檢查后端日志
└── 檢查后端資源狀態(tài)
4 504 Gateway Timeout 深度解析
4.1 504 的定義
504 Gateway Timeout:作為網(wǎng)關(guān)或代理的服務(wù)器未能在規(guī)定時間內(nèi)完成請求。
客戶端 Nginx 后端服務(wù) | | | | ──────── GET / ──────> | | | | ──── 轉(zhuǎn)發(fā)請求 ─────────> | | | | | | (等待中...) | | | | | | 超時! | | | <─── (無響應(yīng)) ────────── | ? | ? ? ? ? ? ? ? ? ? ? ? ? | ? ? ? ? ? ? ? ? ? ? ? ? ? | ? | <──── 504 Gateway ----- | ? ? ? ? ? ? ? ? ? ? ? ? ? | ? | ? ? ? ? Timeout ? ? ? ? | ? ? ? ? ? ? ? ? ? ? ? ? ? | ? | ? ? ? ? ? ? ? ? ? ? ? ? | ? ? ? ? ? ? ? ? ? ? ? ? ? |
4.2 504 的典型觸發(fā)場景
場景一:后端處理時間過長
# Nginx 超時配置
server {
listen 80;
server_name example.com;
# FastCGI 超時設(shè)置
fastcgi_connect_timeout 60s; # 連接后端超時
fastcgi_send_timeout 60s; # 發(fā)送請求超時
fastcgi_read_timeout 60s; # 讀取響應(yīng)超時
# Proxy 超時設(shè)置
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
location / {
fastcgi_pass 127.0.0.1:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
場景二:慢查詢導(dǎo)致 PHP-FPM 超時
# PHP-FPM 超時配置 # /etc/php-fpm.d/www.conf request_terminate_timeout = 30s # 單個請求超時 request_slowlog_timeout = 10s # 慢查詢?nèi)罩鹃撝? # 查看 PHP-FPM 慢日志 tail -50 /var/log/php-fpm/www-slow.log # 找到執(zhí)行時間過長的腳本 cat /var/log/php-fpm/www-slow.log # [07-Jan-2026 1045] [pool www] pid 12345 # script: /var/www/html/api.php # call: mysqli_query() # timeout: 30s elapsed
場景三:數(shù)據(jù)庫連接超時
options(MYSQLI_OPT_CONNECT_TIMEOUT,5);
// 設(shè)置讀超時
$conn->options(MYSQLI_OPT_READ_TIMEOUT,30);
// 設(shè)置寫超時
$conn->options(MYSQLI_OPT_WRITE_TIMEOUT,30);
// 執(zhí)行查詢
$result = $conn->query("SELECT * FROM large_table");
?>
場景四:Nginx 等待后端響應(yīng)超時
# 典型場景:API 接口處理時間過長 upstream backend { server 127.0.0.1:8080; keepalive 32; } server { listen 80; server_name api.example.com; # API 超時配置(較長) proxy_connect_timeout 300s; proxy_send_timeout 300s; proxy_read_timeout 300s; # 大文件上傳場景 client_max_body_size 100m; proxy_read_timeout 600s; location /api/ { proxy_pass http://backend; proxy_http_version 1.1; proxy_set_header Connection ""; proxy_set_header Host $host; } }
4.3 504 排查流程圖
504 錯誤發(fā)生 │ ├── Step 1: 檢查是哪個超時 │ ├── Nginx -> 后端:proxy_read_timeout │ ├── FastCGI:fastcgi_read_timeout │ └── 后端 PHP:max_execution_time │ ├── Step 2: 檢查后端日志 │ ├── PHP-FPM 慢日志 │ ├── 后端應(yīng)用日志 │ └── 數(shù)據(jù)庫慢查詢?nèi)罩? │ ├── Step 3: 檢查后端性能 │ ├── CPU 使用率 │ ├── 內(nèi)存使用率 │ └── 數(shù)據(jù)庫連接池 │ └── Step 4: 優(yōu)化方案 ├── 增加超時時間 ├── 優(yōu)化后端代碼 └── 使用異步處理
4.4 超時配置綜合示例
# /etc/nginx/nginx.conf
# 全局超時配置
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# FastCGI 全局配置
fastcgi_connect_timeout 60s;
fastcgi_send_timeout 60s;
fastcgi_read_timeout 60s;
fastcgi_buffering_timeout 60s;
# uWSGI 超時配置
uwsgi_connect_timeout 60s;
uwsgi_send_timeout 60s;
uwsgi_read_timeout 60s;
server {
listen 80;
server_name example.com;
# 默認(rèn)頁面配置
location / {
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
# 靜態(tài)資源(較短超時)
location /static/ {
proxy_pass http://static_backend;
proxy_connect_timeout 10s;
proxy_read_timeout 30s;
expires 1d;
}
# API 接口(較長超時)
location /api/ {
proxy_pass http://api_backend;
proxy_connect_timeout 300s;
proxy_read_timeout 300s;
}
# 上傳接口(更長超時)
location /upload/ {
proxy_pass http://upload_backend;
proxy_connect_timeout 600s;
proxy_read_timeout 600s;
client_max_body_size 500m;
}
# 錯誤頁面
error_page 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
internal;
}
}
5 三種錯誤的對比
5.1 核心區(qū)別對比表
| 特性 | 502 Bad Gateway | 503 Service Unavailable | 504 Gateway Timeout |
|---|---|---|---|
| 含義 | 網(wǎng)關(guān)收到無效響應(yīng) | 服務(wù)暫時不可用 | 網(wǎng)關(guān)等待超時 |
| 問題位置 | 后端連接/后端崩潰 | 限流/過載/維護(hù) | 后端處理太慢 |
| Nginx 視角 | 連接失敗 | 連接成功但拒絕服務(wù) | 連接成功但響應(yīng)超時 |
| 常見原因 | 后端未啟動、端口錯誤 | 限流、worker 耗盡 | 慢查詢、接口耗時過長 |
| 解決方向 | 檢查后端服務(wù) | 擴(kuò)容、限流、等待 | 優(yōu)化后端代碼 |
| HTTP 方法 | 所有方法 | 所有方法 | 通常 GET/POST |
5.2 響應(yīng)時間對比
502: ████????????????????? 立即返回(連接失?。?503: ████????????????????? 立即返回(限流拒絕) 504: ██████████████████████ 等待超時后返回
5.3 日志特征對比
# Nginx 錯誤日志示例 # 502 - 后端連接被拒絕 2026/01/15 1045 [error] 12345#0: *1 connect() failed (111: Connection refused) while connecting to upstream, client: 192.168.1.100, server: example.com, request: "GET / HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000", host: "example.com" # 502 - 后端無響應(yīng) 2026/01/15 1000 [error] 12345#0: *2 no live connection while connecting to upstream, client: 192.168.1.101, server: example.com, request: "GET /api/data HTTP/1.1", upstream: "http://127.0.0.1:8080" # 503 - 限流觸發(fā) 2026/01/15 1000 [error] 12345#0: *3 limiting connections by zone "addr" while connecting to upstream, client: 192.168.1.102, server: example.com, request: "GET / HTTP/1.1", upstream: "http://backend" # 503 - 維護(hù)模式 2026/01/15 1000 [error] 12345#0: *4 maintenance mode, client: 192.168.1.103, server: example.com, request: "GET / HTTP/1.1" # 504 - FastCGI 超時 2026/01/15 1000 [error] 12345#0: *5 upstream timed out (110: Connection timed out) while reading response header from upstream, client: 192.168.1.104, server: example.com, request: "GET /slow-api HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000", host: "example.com" # 504 - Proxy 超時 2026/01/15 1000 [error] 12345#0: *6 upstream timed out (110: Connection timed out) while reading response header from upstream, client: 192.168.1.105, server: example.com, request: "GET /heavy-query HTTP/1.1", upstream: "http://127.0.0.1:8080"
6 實(shí)戰(zhàn)排障案例
案例一:502 后端服務(wù)崩潰
現(xiàn)象:網(wǎng)站間歇性出現(xiàn) 502 錯誤
排查過程:
# 1. 檢查 Nginx 錯誤日志 tail -100 /var/log/nginx/error.log | grep 502 # 輸出: # 2026/01/15 1045 [error] 12345#0: *1 connect() failed (111: Connection refused) while connecting to upstream # 2. 檢查 PHP-FPM 狀態(tài) systemctl status php-fpm # 輸出:php-fpm.service - PHP FastCGI Process Manager # Active: inactive (dead) since Thu 2026-01-15 1000 CST # 3. 檢查系統(tǒng)資源(OOM) dmesg | grep -i"out of memory" # 輸出: # [12543.123456] php-fpm[12345]: oom-kill: victim=12345 # 4. 檢查內(nèi)存使用 free -h # total used free shared buff/cache available # Mem: 7.6Gi 7.2Gi 128Mi 45Mi 200Mi 80Mi # Swap: 2.0Gi 1.8Gi 200Mi # 5. 查看 PHP-FPM 配置 cat /etc/php-fpm.d/www.conf | grep -E"^pm|^max_children|^request_terminate" # pm.max_children = 50 # request_terminate_timeout = 30
根因:PHP-FPM worker 進(jìn)程耗盡內(nèi)存,被 OOM Killer 殺死后服務(wù)停止。
解決:
# 1. 臨時:啟動 PHP-FPM sudo systemctl start php-fpm # 2. 調(diào)整 PHP-FPM 配置 # /etc/php-fpm.d/www.conf [www] pm = dynamic pm.max_children = 20 # 減小,避免內(nèi)存耗盡 pm.start_servers = 3 pm.min_spare_servers = 2 pm.max_spare_servers = 5 pm.max_requests = 200 # 減少每個 worker 處理請求數(shù),防止內(nèi)存泄漏 # 3. 調(diào)整 PHP 內(nèi)存限制 php_admin_value[memory_limit] = 128M # 4. 重啟服務(wù) sudo systemctl restart php-fpm sudo systemctl restart nginx
案例二:504 慢查詢超時
現(xiàn)象:查詢接口頻繁超時,返回 504
排查過程:
# 1. 查看 Nginx 錯誤日志 grep 504 /var/log/nginx/error.log | tail -20 # 輸出: # upstream timed out (110: Connection timed out) while reading response header # 2. 查看 PHP-FPM 慢日志 cat /var/log/php-fpm/www-slow.log # [07-Jan-2026 1400] [pool www] pid 12345 # script: /var/www/html/api/report.php # call: mysqli_query() # timeout: 30s # 3. 進(jìn)入 MySQL 檢查慢查詢 mysql -u root -p -e"SHOW PROCESSLIST;" # 輸出: # | Id | User | db | Command | Time | State | Info | # | 45 | app | mydb | Query | 125 | Sending data | SELECT * FROM huge_table | # 4. 查看慢查詢?nèi)罩九渲?mysql -u root -p -e"SHOW VARIABLES LIKE 'slow_query%';" # slow_query_log = ON # slow_query_log_file = /var/log/mysql/slow.log # 5. 查看最近的慢查詢 tail -20 /var/log/mysql/slow.log # Query_time: 45.234521 Lock_time: 0.000023 Rows_sent: 500000 Rows_examined: 5000000 # SELECT * FROM huge_table WHERE created_at < '2026-01-01';
根因:SQL 查詢沒有索引,全表掃描導(dǎo)致查詢時間過長。
解決:
prepare("SELECT * FROM huge_table WHERE created_at < ? ORDER BY id LIMIT ? OFFSET ?");
$stmt->bind_param("sii", $date, $perPage, $offset);
$stmt->execute();
?>
-- 添加索引 ALTERTABLEhuge_tableADDINDEXidx_created_at (created_at); ALTERTABLEhuge_tableADDINDEXidx_created_at_id (created_at,id); -- 驗(yàn)證索引 EXPLAINSELECT*FROMhuge_tableWHEREcreated_at '2026-01-01'?ORDER?BY?id?LIMIT?100;
案例三:503 限流導(dǎo)致服務(wù)不可用
現(xiàn)象:促銷活動期間,大量用戶收到 503 錯誤
排查過程:
# 1. 檢查 Nginx 限流配置 grep -r"limit_req"/etc/nginx/ # /etc/nginx/nginx.conf: limit_req_zone $binary_remote_addr zone=one:10m rate=10r/s; # 2. 查看限流觸發(fā)情況 tail -100 /var/log/nginx/error.log | grep"limiting" # 輸出: # limiting requests, excess: 15.5 by zone "one" # 3. 檢查連接數(shù) ss -ant | grep :80 | wc -l # 輸出:15000 # 4. 查看 PHP-FPM 狀態(tài) curl http://127.0.0.1/status # pool: www # accepted conn: 1000000 # listen queue: 50 # max listen queue: 100 # active processes: 50 # max children reached: 1 # 5. 統(tǒng)計(jì) 503 錯誤 grep"503"/var/log/nginx/access.log | wc -l # 輸出:12345
根因:限流配置過于嚴(yán)格,高峰期正常請求被拒絕。
解決:
# 調(diào)整限流配置
# /etc/nginx/nginx.conf
# 限流配置 - 提高限制
limit_req_zone $binary_remote_addr zone=one:100m rate=100r/s;
limit_req_zone $binary_remote_addr zone=api:50m rate=50r/s;
server {
listen 80;
server_name example.com;
# 普通頁面 - 較高限制
location / {
limit_req zone=one burst=200 nodelay;
proxy_pass http://backend;
}
# API 接口 - 較低限制(防止濫用)
location /api/ {
limit_req zone=api burst=50 nodelay;
proxy_pass http://api_backend;
}
# 靜態(tài)資源 - 幾乎不限流
location /static/ {
limit_req zone=one burst=500;
proxy_pass http://static_backend;
expires 7d;
add_header Cache-Control "public";
}
}
7 監(jiān)控與告警配置
7.1 監(jiān)控 5xx 錯誤率
#!/bin/bash
# monitor_5xx.sh - 監(jiān)控 5xx 錯誤率
LOG_FILE="/var/log/nginx/access.log"
ALERT_THRESHOLD=5 # 5xx 錯誤百分比閾值
# 獲取當(dāng)前分鐘的錯誤統(tǒng)計(jì)
current_minute=$(date +"%d/%b/%Y:%H:%M")
total_requests=$(grep"$current_minute""$LOG_FILE"| wc -l)
error_5xx=$(grep"$current_minute""$LOG_FILE"| awk'$9 ~ /^5[0-9][0-9]$/'| wc -l)
if[$total_requests-gt 0 ];then
error_rate=$(echo"scale=2;$error_5xx* 100 /$total_requests"| bc)
echo"總請求:$total_requests"
echo"5xx 錯誤:$error_5xx"
echo"錯誤率:${error_rate}%"
if(( $(echo"$error_rate>$ALERT_THRESHOLD"| bc -l) ));then
echo" 告警:5xx 錯誤率超過${ALERT_THRESHOLD}%"
# 發(fā)送告警(可接入 Prometheus/Zabbix)
fi
else
echo"當(dāng)前分鐘無請求"
fi
7.2 Prometheus 告警規(guī)則
# prometheus_5xx_alerts.yml
groups:
-name:nginx_5xx_alerts
rules:
-alert:NginxHigh502ErrorRate
expr:|
sum(rate(nginx_http_requests_total{status=~"502"}[5m]))
/ sum(rate(nginx_http_requests_total[5m])) * 100 > 5
for:2m
labels:
severity:critical
annotations:
summary:"Nginx 502 錯誤率過高"
description:"502 錯誤率超過 5%,當(dāng)前值:{{ $value }}%"
-alert:NginxHigh503ErrorRate
expr:|
sum(rate(nginx_http_requests_total{status=~"503"}[5m]))
/ sum(rate(nginx_http_requests_total[5m])) * 100 > 5
for:2m
labels:
severity:warning
annotations:
summary:"Nginx 503 錯誤率過高"
description:"503 錯誤率超過 5%,當(dāng)前值:{{ $value }}%"
-alert:NginxHigh504ErrorRate
expr:|
sum(rate(nginx_http_requests_total{status=~"504"}[5m]))
/ sum(rate(nginx_http_requests_total[5m])) * 100 > 5
for:2m
labels:
severity:warning
annotations:
summary:"Nginx 504 錯誤率過高"
description:"504 錯誤率超過 5%,當(dāng)前值:{{ $value }}%"
7.3 Zabbix 監(jiān)控模板
# Zabbix Agent 配置
# /etc/zabbix/zabbix_agentd.d/nginx_status.conf
UserParameter=nginx.active_connections,curl -s http://localhost/status | grep'Active connections:'| awk'{print $3}'
UserParameter=nginx.accepts,curl -s http://localhost/status | awk'/^s+[0-9]+ [0-9]+ [0-9]+/ {print $1}'
UserParameter=nginx.handled,curl -s http://localhost/status | awk'/^s+[0-9]+ [0-9]+ [0-9]+/ {print $2}'
UserParameter=nginx.requests,curl -s http://localhost/status | awk'/^s+[0-9]+ [0-9]+ [0-9]+/ {print $3}'
UserParameter=nginx.5xx_rate,grep -c' 502 | 503 | 504 '/var/log/nginx/access.log
8 總結(jié)與檢查清單
三種錯誤對比總結(jié)
502 Bad Gateway: 問題:后端無法連接 原因:后端服務(wù)未啟動、端口錯誤、后端崩潰 排查:檢查后端服務(wù)、檢查端口、檢查日志 503 Service Unavailable: 問題:后端拒絕服務(wù) 原因:限流、過載、維護(hù)模式、worker 耗盡 排查:檢查限流配置、檢查后端負(fù)載、檢查維護(hù)開關(guān) 504 Gateway Timeout: 問題:后端響應(yīng)超時 原因:處理時間過長、慢查詢、接口耗時 排查:檢查后端日志、檢查慢查詢、優(yōu)化代碼
排查檢查清單
#!/bin/bash
# comprehensive_5xx_check.sh - 5xx 錯誤綜合排查
echo"============================================"
echo" 502/503/504 錯誤綜合排查"
echo"============================================"
# Nginx 服務(wù)
echo""
echo"[1] Nginx 服務(wù)狀態(tài)"
systemctl is-active nginx &&echo"? 運(yùn)行中"||echo"? 未運(yùn)行"
ss -tlnp | grep :80 | head -3
# 后端服務(wù)
echo""
echo"[2] 后端服務(wù)狀態(tài)"
forserviceinphp-fpm php80-php-fpm php74-php-fpm node java python;do
ifsystemctl list-units --type=service | grep -q"$service";then
systemctl is-active"$service"&&echo"?$service運(yùn)行中"||echo"$service未運(yùn)行"
fi
done
# 端口監(jiān)聽
echo""
echo"[3] 關(guān)鍵端口監(jiān)聽"
ss -tlnp | grep -E":80|:443|:8080|:9000|:9001"| head -10
# 近 5 分鐘 5xx 統(tǒng)計(jì)
echo""
echo"[4] 近 5 分鐘 5xx 錯誤統(tǒng)計(jì)"
current_time=$(date +"%d/%b/%Y:%H:%M")
grep"$current_time"/var/log/nginx/access.log 2>/dev/null | awk'$9 ~ /^5[0-9][0-9]$/ {print $9}'| sort | uniq -c
# Nginx 錯誤日志
echo""
echo"[5] Nginx 錯誤日志(最近 20 條)"
tail -20 /var/log/nginx/error.log 2>/dev/null
# PHP-FPM 狀態(tài)
echo""
echo"[6] PHP-FPM 狀態(tài)(如果有)"
curl -s http://127.0.0.1/status 2>/dev/null ||echo"PHP-FPM status 頁面未配置"
# 連接數(shù)
echo""
echo"[7] 當(dāng)前連接數(shù)"
ss -ant | wc -l
echo""
echo"============================================"
快速響應(yīng)流程
收到 5xx 告警
│
├── 立即檢查
│ ├── Nginx 是否運(yùn)行
│ ├── 后端服務(wù)是否運(yùn)行
│ └── 端口是否監(jiān)聽
│
├── 查看日志
│ ├── Nginx error.log
│ ├── 后端服務(wù)日志
│ └── PHP-FPM 慢日志(如有)
│
├── 臨時處置
│ ├── 重啟后端服務(wù)
│ ├── 調(diào)整超時配置
│ └── 臨時關(guān)閉限流
│
└── 根因分析
├── 分析錯誤日志
├── 檢查慢查詢
├── 優(yōu)化配置或代碼
└── 完善監(jiān)控告警
常用命令速查
# 查看 502 錯誤日志 grep 502 /var/log/nginx/error.log # 查看 503/504 錯誤日志 grep -E"503|504"/var/log/nginx/error.log # 統(tǒng)計(jì) 5xx 錯誤 awk'$9 ~ /^5[0-9][0-9]$/'/var/log/nginx/access.log | wc -l # 檢查后端服務(wù) systemctl status php-fpm ps aux | grep php-fpm # 檢查端口 ss -tlnp | grep :9000 # 測試后端連接 nc -zv 127.0.0.1 9000 telnet 127.0.0.1 9000 # PHP-FPM 狀態(tài) curl http://127.0.0.1/status # 查看慢日志 tail -50 /var/log/php-fpm/www-slow.log
-
服務(wù)器
+關(guān)注
關(guān)注
14文章
10326瀏覽量
91675 -
HTTP協(xié)議
+關(guān)注
關(guān)注
0文章
68瀏覽量
10680
原文標(biāo)題:網(wǎng)站 502、503、504 的區(qū)別是什么?運(yùn)維別再混著說了
文章出處:【微信號:magedu-Linux,微信公眾號:馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
[轉(zhuǎn)]生產(chǎn)環(huán)境常見的HTTP狀態(tài)碼列表
三種跨時鐘域處理的方法
LwIP協(xié)議棧開發(fā)嵌入式網(wǎng)絡(luò)的三種方法有何關(guān)系
功放三極管的三種工作狀態(tài)工作狀態(tài)
功放管的三種工作狀態(tài)
電路的三種工作狀態(tài)分別是什么
Allegro網(wǎng)絡(luò)的MAC、DHCP 和 HTTP三種協(xié)議解析
HTTP狀態(tài)碼你知道幾個
繼電保護(hù)的三種狀態(tài)解析
如何理解HTTP協(xié)議是無狀態(tài)的
示波器的三種觸發(fā)模式
mosfet的三種工作狀態(tài)及工作條件是什么
示波器的三種觸發(fā)模式
HTTP協(xié)議三種狀態(tài)碼的觸發(fā)場景和排查方法
評論