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

PHP cURL 超時設定完整指南:秒級與毫秒級精準控制

     編輯:PHP 綜合知識

HTTP 請求超時控制是網路程式健壯性的關鍵。PHP cURL 提供多層次超時參數,涵蓋連線階段、資料傳輸階段、DNS 快取等。本文系統整理各超時選項差異,提供秒級與毫秒級設定範例,並解釋 CURLOPT_NOSIGNAL 在毫秒級超時下的必要性。

cURL 核心超時參數對照表

常數單位控制階段備註
CURLOPT_TIMEOUT秒整個請求(連線+傳輸)最長執行時間最常用,預設 0(不限制)
CURLOPT_TIMEOUT_MS毫秒整個請求最長執行毫秒數需 cURL 7.16.2+、PHP 5.2.3+
CURLOPT_CONNECTTIMEOUT秒連線階段等待時間(TCP 握手、SSL 協商)0 表示無限等待
CURLOPT_CONNECTTIMEOUT_MS毫秒連線階段等待毫秒數需 cURL 7.16.2+、PHP 5.2.3+
CURLOPT_DNS_CACHE_TIMEOUT秒DNS 快取存活時間預設 120 秒,減少重複解析

範例 1:基本秒級超時設定

$ch = curl_init();
curl_setopt_array($ch, [
    CURLOPT_URL            => $url,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT        => 60,        // 整個請求最長 60 秒
    CURLOPT_CONNECTTIMEOUT => 10,        // 連線最長等待 10 秒
    CURLOPT_HTTPHEADER     => $headers,
    CURLOPT_USERAGENT      => $_SERVER['HTTP_USER_AGENT'] ?? 'PHP-cURL',
]);
$response = curl_exec($ch);
if (curl_errno($ch)) {
    // 錯誤碼 28 = CURLE_OPERATION_TIMEDOUT
    throw new RuntimeException(curl_error($ch), curl_errno($ch));
}
curl_close($ch);

範例 2:毫秒級精準超時(關鍵:CURLOPT_NOSIGNAL)

當使用 CURLOPT_TIMEOUT_MS 或 CURLOPT_CONNECTTIMEOUT_MS 時,**必須**啟用 CURLOPT_NOSIGNAL => 1,否則 cURL 會使用 Unix 訊號(SIGALRM)計時,導致多執行緒環境(如 PHP-FPM、Swoole)下訊號衝突、程式崩潰或超時不準。

$ch = curl_init();
curl_setopt_array($ch, [
    CURLOPT_URL              => $url,
    CURLOPT_RETURNTRANSFER   => true,
    CURLOPT_NOSIGNAL         => 1,       // ★ 必須啟用,避免訊號衝突
    CURLOPT_TIMEOUT_MS       => 500,     // 總超時 500 ms
    CURLOPT_CONNECTTIMEOUT_MS=> 200,     // 連線超時 200 ms
]);
$response = curl_exec($ch);

原理補充:cURL 傳統用 alarm() + 訊號處理器實現超時,但在多執行緒下訊號可能被錯誤執行緒捕獲。NOSIGNAL 改用輪詢機制,犧牲極微精度換取執行緒安全。

常見誤區與最佳實踐

  1. 只設 CURLOPT_TIMEOUT 忽略 CONNECTTIMEOUT:若遠端主機掛掉(TCP SYN 無回應),連線階段會阻塞至系統預設(通常 75 秒),導致實際超時遠超預期。永遠同時設定兩者。
  2. 毫秒級超時未開 NOSIGNAL:生產環境必現隨機崩潰或超時失效。
  3. DNS 快取過久:服務遷移 IP 後,客戶端仍解析舊 IP。建議 CURLOPT_DNS_CACHE_TIMEOUT => 60 或定期 curl_close() 釋放 handle 刷新快取。
  4. 超時錯誤碼辨識:curl_errno() === 28 (CURLE_OPERATION_TIMEDOUT) 代表超時,28 含連線與傳輸兩階段,可結合 curl_getinfo($ch, CURLINFO_CONNECT_TIME) 判斷具體階段。
  5. 搭配 Guzzle/Httplug:現代專案建議使用 Guzzle,其 timeout (float 秒) 與 connect_timeout 內部自動處理 NOSIGNAL 與單位換算,API 更安全。

總結速查卡

  • 一般專案:CURLOPT_TIMEOUT=30, CURLOPT_CONNECTTIMEOUT=10
  • 高併發/微服務:CURLOPT_NOSIGNAL=1, CURLOPT_TIMEOUT_MS=2000, CURLOPT_CONNECTTIMEOUT_MS=500
  • 長連線/串流:CURLOPT_TIMEOUT=0 (不限總時長) + 應用層心跳控制

精準的超時控制能有效防止資源耗盡、級聯失敗,是分散式系統穩定性的基石。

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