線上 Nginx + PHP-FPM 環境中,php-cgi(或 php-fpm worker)進程佔用 CPU 100% 是常見故障。本文從日誌分析、配置調優、代碼層面根治三個維度,提供系統化解決路徑。
/home/hosts_log/(按站點 ID 分目錄)/usr/local/php_fcgi/logs/php-fpm.log/usr/local/php_fcgi/logs/slow.log(需開啟 request_slowlog_timeout)eval(base64_decode(...))、ddos 關鍵字、大量異常 POST 請求 → 立即隔離機器、清理木馬、修復漏洞。slow.log 大量記錄 file_get_contents()、curl_exec() 等外部請求函數耗時極長,說明業務代碼阻塞在等待下游響應。核心參數:request_terminate_timeout(單位:秒,0 表示關閉)
; /usr/local/php/etc/php-fpm.conf
30s
作用:強制終止執行超時的請求,防止所有 worker 被長連接佔滿導致 502 Bad Gateway。
副作用:若並發高、下游慢,依然會頻繁觸發終止,吞吐率急劇下降。
file_get_contents() 默認無超時,且 PHP max_execution_time 在 CLI/FPM 模式下對流操作不生效。一旦目標服務器無響應,進程永久阻塞。
<?php
$ctx = stream_context_create([
'http' => [
'timeout' => 3, // 3 秒連接+讀取總超時
'method' => 'GET',
]
]);
$content = file_get_contents("https://api.example.com/data", 0, $ctx);
// 建議封裝為通用 http_get($url, $timeout=3) 函數
?>
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CONNECTTIMEOUT => 2,
CURLOPT_TIMEOUT => 5,
CURLOPT_SSL_VERIFYPEER => false, // 內網可關閉驗證
]);
$data = curl_exec($ch);
curl_close($ch);
strace -p PID 或 gdb 定位行號。opcache.validate_timestamps=0 導致代碼更新不生效,誤觸發異常邏輯。top -c 確認高 CPU 進程 PIDstrace -p PID 觀察系統調用(若卡在 poll/read 多為網絡等待)kill -9 PID 釋放 worker 槽位(FPM 會自動重生)核心原則:配置兜底(request_terminate_timeout),代碼必須有超時(stream context / cURL),日誌要可查(slowlog),監控要及時。