首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

Nginx 504 Gateway Time-out 完整排查與解決實戰

     編輯:PHP 相關知識

Nginx 504 Gateway Time-out 完整排查與解決實戰

在處理大量資料匯出、長時間運算任務時,Nginx 504 Gateway Time-out 是最常見的阻礙。本文記錄一次 Excel 匯出 2 萬筆、每筆 50 欄位導致的 10 分鐘超時案例,完整呈現從現象分析、配置調整到根因解決的全過程。

現象重現

  • 任務:後台匯出 20,000 筆會員資料為 Excel
  • 執行約 10 分鐘後,瀏覽器顯示 504 Gateway Time-out
  • Nginx 錯誤日誌記錄:upstream timed out (110: Connection timed out) while reading response header from upstream

核心成因分析

504 錯誤本質是 Nginx 作為反向代理,在等待上游(PHP-FPM)回應時超時。常見三大原因:

  1. 程式處理大量資料/死迴圈,執行時間過長
  2. 資料庫連線建立失敗且無超時機制,導致持續阻塞
  3. 程式內發起外部 HTTP 請求,回應過慢

本案例屬於第 1 類:PHP 腳本執行時間超過 Nginx 與 PHP-FPM 的預設超時閾值。

分層超時配置詳解

請求鏈路:Client → Nginx → PHP-FPM → PHP Script,每層都有獨立超時控制:

1. Nginx 層(fastcgi 參數)

# /etc/nginx/nginx.conf 或站點配置中
location ~ \.php$ {
    fastcgi_connect_timeout 1200s;  # 連線上游超時,預設 60s
    fastcgi_send_timeout 1200s;     # 向上游傳送請求超時,預設 60s
    fastcgi_read_timeout 1200s;     # 等待上游回應超時,預設 60s **最關鍵**
    
    fastcgi_buffer_size 64k;
    fastcgi_buffers 4 64k;
    fastcgi_busy_buffers_size 128k;
    fastcgi_temp_file_write_size 256k;
}

關鍵說明:

  • fastcgi_read_timeout:Nginx 等待 PHP-FPM 回應的最長時間,**必須大於 PHP 腳本最大執行時間**
  • 預設 60 秒,官方建議不超過 75 秒,但長任務需適度放寬

2. PHP-FPM 層

; /etc/php-fpm.d/www.conf
request_terminate_timeout = 0  ; 0 表示無限制,單位秒
; 預設為 0,但受限於 php.ini 的 max_execution_time

3. PHP 腳本層

; php.ini
max_execution_time = 300  ; CLI 模式無效,僅對 mod_php 生效

; PHP 程式碼中動態設定(最高優先級)
set_time_limit(0);  // 0 = 無限制,單位秒

重要機制: set_time_limit() 是**重置計時器**,而非累加。例如預設 30 秒,執行 25 秒後呼叫 set_time_limit(20),總允許時間變為 45 秒(25+20)。

實戰排查步驟

步驟 1:調整 Nginx 與 PHP-FPM 超時

修改配置後重載服務:

nginx -t && systemctl reload nginx
systemctl reload php-fpm

結果:504 錯誤消失,但頁面空白、無檔案下載 → PHP 仍在超時中終止。

步驟 2:定位 PHP 執行階段超時

  • 檢查程式碼無 set_time_limit() 呼叫
  • PHP-FPM request_terminate_timeout = 0 已關閉強制終止
  • 懷疑 max_execution_time 或 PHP 內部機制生效

步驟 3:程式碼層面強制移除限制

在匯出函數入口加入:

// 匯出函數開頭
set_time_limit(0);  // 移除執行時間限制
ini_set('memory_limit', '512M');  // 同步調大記憶體

結果:匯出成功完成,檔案正常下載。

最佳實踐總結

配置建議矩陣

層級參數長任務建議值說明
Nginxfastcgi_read_timeout3600s (1小時)視最大任務時長而定,預留緩衝
PHP-FPMrequest_terminate_timeout0 (關閉)交由腳本層控制
PHP 腳本set_time_limit()0 或具體秒數程式碼中動態控制,彈性最高
PHP 腳本memory_limit512M/1G大量資料處理必須調大

架構層面優化方案

若任務常態化超過 5 分鐘,建議採用**非同步處理架構**:

  1. 佇列系統:Laravel Queue、Redis + Worker、Gearman
  2. 前端輪詢/WebSocket:即時回報進度
  3. 分塊處理:將 2 萬筆拆分為 20 批次,每批 1 千筆
  4. 串流輸出:使用 fopen('php://output') 邊生成邊輸出,避免記憶體飆升

常見誤區提醒

  • ❌ 只改 Nginx 不改 PHP-FPM/腳本層 → 仍會超時
  • ❌ 以為 max_execution_time 對 CLI/FPM 生效 → **無效**
  • ❌ 將所有超時設為極大值 → 佔用 Worker 進程,導致併發能力下降
  • ✅ 分層配置 + 程式碼精準控制 + 非同步架構 = 穩健方案

此案例印證了「分層超時、逐層突破」的排查邏輯。遇到 504 時,請沿著請求鏈路由外而內、由基礎設施到應用程式碼逐層檢查,定能精準定位瓶頸。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved