Windows環境下Apache+PHP長任務崩潰解決方案,日志錯誤為:php-cgi.exe exit(busy timeout), return code 9
一、問題概況
上傳Excel數據進行計算入庫的程序,在執行一次數據量大的Excel時出現。基本的max_execution_time 、memory_limit 都已設置,程序每次執行大約8分鐘左右后會出現500的服務器異常(thinkphp框架會跳轉出現Error控制器不存在的異常),且無更詳細的錯誤信息與描述。
二、問題分析流程
1、對程序內上傳的Excel數據做截斷測試(二分),確認程序以及上傳文件正常。
2、逐步簡化測試程序代碼,排查是否某存在單次耗時過長能優化的代碼或者SQL查詢。經測試未檢測出明顯耗時和能優化的代碼。
3、程序涉及Mysql事務,檢查相關錯誤日志+程序注釋事務內數據庫操作進行調試(改用sleep()函數模仿),排除長事務導致的異常。
4、調整PHP超時相關基本配置max_execution_time 、memory_limit測試改動后是否有效,測試后無效。
5、經過上面調試,已發現服務器異常時間大約在8分鐘左右,繼續簡化代碼超時用sleep()代替,最終調試代碼如下:
1 ini_set('max_execution_time',0); 2 ini_set('memory_limit', '2048M'); 3 sleep(600); 4 echo 1;
6、程序使用了框架(Thinkphp),框架外執行調試代碼排除框架導致的異常。
7、檢查PHP錯誤日志同時更換PHP新版本測試,排除PHP版本以及配置問題,防止其他更改過的配置導致異常。
8、經上述測試,目標已鎖定Apache問題,初始查看Apache日志并無記錄明顯錯誤異常。
9、調整Apache錯誤日志等級原crit(嚴重)=>debug(調試),最終定位到php-cgi.exe exit(busy timeout), return code 9的異常信息,開始針對Apache的php-cgi相關配置進行了解和調試。
三、最終解決方案
【常規PHP超時配置項】 [php.ini] max_execution_time = 1200 memory_limit = 1024M [代碼] ini_set('max_execution_time',0); ini_set('memory_limit', '1024M'); 【Apache httpd.conf相關配置】 # 定義服務器等待客戶端請求的最長時間(秒),包括接收請求頭和請求體的總時間? Timeout 1200 # 啟用持久連接,允許同一TCP連接處理多個HTTP請求,減少握手開銷? KeepAlive On # 控制空閑連接保持時間,超過該時限未活動則斷開連接? 與Timeout需保持協調關系(建議KeepAliveTimeout ≤ Timeout)? KeepAliveTimeout 1200 [核心mod_fcgid相關配置] <IfModule mod_fcgid.c> # 定義FastCGI進程I/O操作(讀寫請求/響應數據)的最大超時時間,單位為秒 FcgidIOTimeout 2400 # 強制終止處理請求超過2700秒(45分鐘)的FastCGI進程,用于防止腳本無限阻塞 FcgidBusyTimeout 2700 # 控制空閑FastCGI進程的存活時間。600秒后無請求則回收進程 FcgidIdleTimeout 600 # 單個FastCGI進程的最大生命周期(1小時),超時后自動重啟以釋放潛在內存泄漏 FcgidProcessLifeTime 3600 # FastCGI進程啟動或連接的后端服務超時時間(5分鐘),僅Windows系統有效。UNIX系統依賴Socket機制無此限制? FcgidConnectTimeout 300 </IfModule>

浙公網安備 33010602011771號