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

PHP使用curl_multi_init加载3万URL返回空值,如何控制并发数为10?

问题根源与解决方案

你遇到的问题核心是:一次性把3万个请求句柄全加到curl_multi里了——哪怕CURLMOPT_MAXCONNECTS默认是10,curl会尝试在后台排队处理,但系统的文件句柄、网络带宽等资源根本扛不住这么多并发请求排队,最终导致大量请求超时失败。

要实现严格的「每次仅处理10个请求」,需要分批加载+动态补充的逻辑:先启动第一批10个请求,每完成一个就立刻补上一个新的,始终保持同时活跃的请求数不超过10。


修改后的完整代码

$mh = curl_multi_init();
// 设置总并发连接数上限为10(核心控制项)
curl_multi_setopt($mh, CURLMOPT_MAX_TOTAL_CONNECTIONS, 10);
// 每个主机的最大连接数(可选,按需调整)
curl_multi_setopt($mh, CURLMOPT_MAXCONNECTS, 10);

$requests = [];
$responses = [];
$urlCount = count($urls);
$currentIndex = 0;
$active = 0;

// 加载第一批10个请求
for (; $currentIndex < min(10, $urlCount); $currentIndex++) {
    $url = $urls[$currentIndex];
    $ch = curl_init($url);
    // 复用你的curl配置
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_TIMEOUT, 8);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_HEADER, false);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36');
    
    curl_multi_add_handle($mh, $ch);
    $requests[(int)$ch] = $currentIndex; // 用句柄映射URL索引,保证响应顺序
}

do {
    // 执行多请求并获取活跃连接数
    $execStatus = curl_multi_exec($mh, $active);
    // 等待连接状态变化,避免空循环占用CPU
    if ($execStatus == CURLM_OK) {
        curl_multi_select($mh);
    }

    // 读取所有已完成的请求信息
    while ($info = curl_multi_info_read($mh)) {
        $ch = $info['handle'];
        $urlIndex = $requests[(int)$ch];
        
        // 根据请求结果处理响应
        if ($info['result'] == CURLE_OK) {
            $responses[$urlIndex] = curl_multi_getcontent($ch);
        } else {
            $responses[$urlIndex] = false;
            // 可选:打印错误详情用于排查
            // echo "URL {$urls[$urlIndex]} 失败: " . curl_error($ch) . "\n";
        }

        // 清理已完成的请求句柄
        curl_multi_remove_handle($mh, $ch);
        curl_close($ch);
        unset($requests[(int)$ch]);

        // 加载下一个请求,直到所有URL处理完毕
        if ($currentIndex < $urlCount) {
            $url = $urls[$currentIndex];
            $newCh = curl_init($url);
            // 复用相同配置
            curl_setopt($newCh, CURLOPT_RETURNTRANSFER, true);
            curl_setopt($newCh, CURLOPT_TIMEOUT, 8);
            curl_setopt($newCh, CURLOPT_CONNECTTIMEOUT, 5);
            curl_setopt($newCh, CURLOPT_SSL_VERIFYHOST, false);
            curl_setopt($newCh, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($newCh, CURLOPT_HEADER, false);
            curl_setopt($newCh, CURLOPT_FOLLOWLOCATION, true);
            curl_setopt($newCh, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36');
            
            curl_multi_add_handle($mh, $newCh);
            $requests[(int)$newCh] = $currentIndex;
            $currentIndex++;
        }
    }
} while ($active > 0 || $currentIndex < $urlCount);

// 关闭多请求句柄
curl_multi_close($mh);

// 响应数组与原URL数组顺序一致
// print_r($responses);

关键逻辑说明

  • CURLMOPT_MAX_TOTAL_CONNECTIONS:直接控制curl_multi同时允许的总连接数,设置为10就确保最多同时跑10个请求。
  • 动态补充机制:每次有请求完成就立刻加载下一个未处理的URL,始终保持并发量稳定,避免一次性占用过多系统资源。
  • 响应顺序保证:通过请求句柄映射原URL的索引,最终$responses数组会和输入的$urls数组顺序完全一致。
  • 错误排查:通过curl_multi_info_read获取请求结果状态,能快速定位失败的URL及原因。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 15:13:24