Symfony HttpClient默认不重试,需用RetryableHttpClient包装并显式配置max_retries、delay_ms、http_codes及底层retry_failed=true;非幂等请求如POST默认不重试,须确认服务端幂等支持。

Symfony 本身不自动重试 HTTP 请求,得靠 RetryableHttpClient 显式配置。默认的 HttpClient 发送请求后遇到 503、连接超时等,立刻返回或抛异常,不会重试。
启用 RetryableHttpClient 并配关键选项
必须用 RetryableHttpClient 包裹原始客户端,并传入有效策略参数:
-
max_retries:最大重试次数(如3) -
delay_ms:每次重试前等待毫秒数(如1000,即 1 秒) -
http_codes:明确列出要重试的状态码,比如[500, 502, 503, 504, 429];漏掉429就不会对限流响应重试
示例代码:
$client = new RetryableHttpClient(
new HttpClient(),
[
'max_retries' => 3,
'delay_ms' => 1000,
'http_codes' => [500, 502, 503, 504, 429],
]
);
$response = $client->request('GET', 'https://api.example.com/data');
?>
注意 POST 等非幂等请求的重试风险
默认情况下,RetryableHttpClient 只对 GET 和 HEAD 重试。POST/PUT/DELETE 不会自动重试,因为重复提交可能造成数据异常(如重复下单)。
- 若业务确认服务端支持幂等(例如带
Idempotency-Key头),可手动开启:'retry_strategy' => ['methods' => ['GET', 'HEAD', 'POST']] - 但更稳妥的做法是:在调用处用
try/catch捕获TransportException,再根据业务逻辑决定是否手动重发 - 注意:重试时请求体(如 JSON 字符串)会被重新序列化;若 body 是文件句柄或闭包,第二次会失败
别忘了底层 HttpClient 的 retry_failed 开关
这是最常被忽略的坑:即使 RetryableHttpClient 配了 max_retries,如果底层 HttpClient 没启用 retry_failed,重试完全不生效。
-
retry_failed默认为false,需显式设为true - 正确写法是把选项传给
HttpClient构造器,而不是只传给RetryableHttpClient
new HttpClient(['retry_failed' => true]), // 关键!
[/* 其他重试参数 */]
);
超时与重试的关系要理清
重试只针对“已发出但失败”的请求,比如网络断开、服务返回 503。如果请求因 timeout 被主动取消,它不算“失败”,不会触发重试。
- 确保
timeout设置合理(如10.0秒),避免过短导致请求还没发出去就被砍掉 -
max_duration是总耗时上限,也会影响重试能否完成 - 异步使用
Promise时,重试只作用于单个 promise,不跨并发共享状态


















