You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel HTTP Client Pool捕获ConnectException及并发请求故障处理方案

问题根因

你当前的写法无效是因为两个核心错误:

  • 异步请求的异常不会在创建Promise的同步阶段抛出,你套在$pool->get()外面的try/catch完全不会触发
  • Laravel HTTP客户端的pool是批量并发执行所有你返回的Promise,你在循环里写的重试逻辑只是在创建阶段重复生成请求,没有真正实现请求失败后的重试逻辑
解决方案

我们可以直接利用Laravel HTTP客户端内置的retry方法,配合异常判断逻辑,实现连接异常时自动更换代理重试,不需要自己写循环捕获:

<?php

use GuzzleHttp\Exception\ConnectException;
use Illuminate\Support\Facades\Http;

$responses = Http::pool(function (Illuminate\Http\Client\Pool $pool) use ($params) {
    $url = "https://example.com/api/endpoint?foo=%s";
    $requests = [];

    foreach ($params as $param) {
        $requests[] = $pool->as($param)
            // 配置重试规则:最多重试10次,每次间隔100ms,仅连接异常时重试
            ->retry(10, 100, function (\Exception $e, $request) {
                // 仅当是连接异常时才触发重试
                if ($e instanceof ConnectException) {
                    // 每次重试更换新的代理
                    $request->withOptions(['proxy' => $this->proxyManager->get()]);
                    return true;
                }
                return false;
            })
            // 初始赋值第一个代理
            ->withOptions(['proxy' => $this->proxyManager->get()])
            ->get(sprintf($url, $param));
    }

    return $requests;
});

// 后续可以遍历responses判断每个请求的最终状态
foreach ($responses as $param => $response) {
    if ($response->failed()) {
        // 处理重试10次后仍然失败的情况
        info("参数{$param}请求最终失败", ['error' => $response->toException()?->getMessage()]);
    }
}
注意事项
  • 如果你需要更灵活的重试间隔,可以把retry方法的第二个参数换成回调,实现指数退避之类的逻辑
  • 所有请求还是保持并发执行,每个请求的重试是独立的,不会互相阻塞
  • 如果要获取每个请求的异常信息,可以调用$response->toException()方法获取抛出的异常实例
  • 不要在pool的闭包内用dd之类的终止函数,会打断整个并发池的执行

内容的提问来源于stack exchange,提问作者abr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 19:36:05