curl_exec返回false但无报错,需提前设置CURLOPT_TIMEOUT(总耗时)和CURLOPT_CONNECTTIMEOUT(连接阶段);file_get_contents需用stream_context_set_default或stream_context_create配置timeout;Guzzle超时抛出ConnectException或RequestException;自定义封装须注意信号处理、句柄清理与平台差异。

curl_exec 返回 false 但没报错?检查 CURLOPT_TIMEOUT 和 CURLOPT_CONNECTTIMEOUT
PHP 用 curl_exec 调用远程服务时,超时不会抛出异常,而是静默返回 false,同时 curl_error 可能为空或只显示“Operation timed out”。关键在提前设置超时参数:
-
CURLOPT_TIMEOUT控制整个请求最大耗时(含连接 + 传输),单位秒,设为10表示 10 秒内没完成就中断 -
CURLOPT_CONNECTTIMEOUT仅控制 TCP 连接建立阶段,建议设为3防止卡在 DNS 或网络不可达 - 两者都必须在
curl_exec前通过curl_setopt设置,运行中修改无效 - 注意:若启用了
CURLOPT_RETURNTRANSFER,curl_exec失败时仍返回false,不能用empty()或== ''判断,必须用=== false
file_get_contents 超时怎么捕获?别忘了 stream_context_set_default
file_get_contents 默认无超时,直接阻塞,必须显式配置上下文。常见错误是只改了当前调用的 context,却没处理默认行为:
- 正确做法:调用前用
stream_context_set_default设置全局默认超时,例如:stream_context_set_default(['http' => ['timeout' => 8]]);
- 或为单次调用构造 context:
$ctx = stream_context_create(['http' => ['timeout' => 5]]); file_get_contents('https://api.example.com', false, $ctx); - 超时发生时,
file_get_contents抛出Warning: file_get_contents(): failed to open stream: Operation timed out,需配合set_error_handler捕获,或用@抑制后检查error_get_last() - 注意:
timeout单位是秒,且不区分连接与读取,不如 cURL 精细
Guzzle HTTP 客户端超时异常类型是什么?
Guzzle 7+ 默认启用异常模式,超时会直接抛出 GuzzleHttp\Exception\ConnectException 或 GuzzleHttp\Exception\RequestException,不是 RuntimeException:
- 连接阶段超时(DNS、TCP 握手)→
ConnectException - 已连接但响应迟迟不来(如服务卡死)→
RequestException,其getHandlerContext()中可查'error' => 'Operation timed out' - 必须在创建 client 时明确传入超时配置:
$client = new \GuzzleHttp\Client(['timeout' => 6, 'connect_timeout' => 2]);
- 若用
throw_on_failure关闭异常模式,则需手动检查$response->getStatusCode()和异常对象是否存在
自定义超时封装函数容易漏掉什么?
自己封装 HTTP 请求函数时,最容易忽略的是信号中断和资源清理:
立即学习“PHP免费学习笔记(深入)”;
- Linux 下,超时可能触发
SIGALRM,但 PHP 默认不处理,需用pcntl_signal+pcntl_signal_dispatch配合,否则脚本卡住 - 未关闭 curl handle(
curl_close)会导致句柄泄漏,尤其在循环调用中;建议用try/finally保证释放 - 超时后不要重试同一 URL 三次——可能对方服务已雪崩,应退避或降级;可用
microtime(true)记录实际耗时,用于监控告警 - 注意:Windows 不支持
pcntl,基于信号的超时方案在此平台无效,必须依赖 cURL 或 Guzzle 的原生超时











