呼叫外部 API 或抓取遠端資源時,若對方伺服器無回應或回應緩慢,PHP 腳本會持續阻塞,嚴重時導致所有工作進程耗盡、服務癱瘓。正確設定連線與讀取超時是撰寫健壯後端的基本功。
<?php
$timeout = [
'http' => [
'timeout' => 5, // 秒,包含連線與讀取總時間
]
];
$ctx = stream_context_create($timeout);
$content = file_get_contents('https://api.example.com/data', false, $ctx);
?>
優點:程式碼簡潔,無需額外擴充。
缺點:難以分別控制連線超時與讀取超時;錯誤處理較弱;大檔案記憶體佔用高。
<?php
$timeout = [
'http' => [
'timeout' => 5,
]
];
$ctx = stream_context_create($timeout);
if ($fp = fopen('https://api.example.com/data', 'r', false, $ctx)) {
while ($chunk = fread($fp, 8192)) {
echo $chunk; // 串流處理,記憶體友善
}
fclose($fp);
}
?>
適用於需逐塊處理大型回應的場景,但錯誤處理仍受限於 Stream Wrapper。
<?php
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => 'https://api.example.com/data',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10, // 總執行超時(秒)
CURLOPT_CONNECTTIMEOUT => 5, // 連線階段超時(秒)
CURLOPT_HTTPHEADER => ['Accept: application/json'],
CURLOPT_USERAGENT => 'MyApp/1.0',
]);
$response = curl_exec($ch);
if ($response === false) {
$errno = curl_errno($ch);
$error = curl_error($ch);
// 記錄錯誤或拋出例外
}
curl_close($ch);
?>
| 常數 | 說明 | 單位 |
|---|---|---|
CURLOPT_TIMEOUT | 整個請求允許的最大秒數 | 秒 |
CURLOPT_TIMEOUT_MS | 整個請求允許的最大毫秒數 | 毫秒 |
CURLOPT_CONNECTTIMEOUT | 建立連線階段的最大等待秒數 | 秒 |
CURLOPT_CONNECTTIMEOUT_MS | 建立連線階段的最大等待毫秒數 | 毫秒 |
CURLOPT_DNS_CACHE_TIMEOUT | DNS 快取存活時間,預設 120 秒 | 秒 |
若使用 CURLOPT_TIMEOUT_MS 或 CURLOPT_CONNECTTIMEOUT_MS,必須同時設定 CURLOPT_NOSIGNAL => 1,避免系統訊號中斷導致超時失效(特別在多執行緒環境)。
file_get_contents 足夠。fopen + fread。