PHP怎样捕获调用服务超时异常_PHP捕获调用超时法【容错】

10次阅读

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

PHP怎样捕获调用服务超时异常_PHP捕获调用超时法【容错】

curl_exec 返回 false 但没报错?检查 CURLOPT_TIMEOUT 和 CURLOPT_CONNECTTIMEOUT

phpcurl_exec 调用远程服务时,超时不会抛出异常,而是静默返回 false,同时 curl_Error 可能为空或只显示“Operation timed out”。关键在提前设置超时参数:

  • CURLOPT_TIMEOUT 控制整个请求最大耗时(含连接 + 传输),单位秒,设为 10 表示 10 秒内没完成就中断
  • CURLOPT_CONNECTTIMEOUT 仅控制 TCP 连接建立阶段,建议设为 3 防止卡在 dns 或网络不可达
  • 两者都必须在 curl_exec 前通过 curl_setopt 设置,运行中修改无效
  • 注意:若启用了 CURLOPT_RETURNTRANSFERcurl_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+ 默认启用异常模式,超时会直接抛出 GuzzleHttpExceptionConnectExceptionGuzzleHttpExceptionRequestException,不是 RuntimeException

  • 连接阶段超时(DNS、TCP 握手)→ ConnectException
  • 已连接但响应迟迟不来(如服务卡死)→ RequestException,其 getHandlerContext() 中可查 'error' => 'Operation timed out'
  • 必须在创建 client 时明确传入超时配置:
    $client = new GuzzleHttpClient(['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 的原生超时

超时不是单纯的“等多久”,它绑定着连接策略、错误分类、系统信号和平台差异——漏掉任意一环,容错就变成假象。

text=ZqhQzanResources