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

多URL状态检测:curl_multi执行过慢问题及代码优化求助

优化curl_multi批量域名检测的速度问题

嘿,我来帮你捋捋为啥你的curl_multi批量检测域名速度慢,再给你几个实打实的优化方案。先把你贴的代码补全展示下(看起来你没写完,但核心逻辑已经能看出来):

class BotCronJobs extends Controller { 
    public function __construct() { } 

    public function index() { 
        $Query = servers::all(); 
        $urls = []; 
        foreach ($Query as $item){ 
            $urls[$item->id] = $item->serverUrl; 
        } 
        var_dump($this->test($urls)); 
    } 

    public function test($urls = []) { 
        $status = []; 
        $mh = curl_multi_init(); 
        foreach($urls as $key => $value){ 
            $ch[$key] = curl_init($value); 
            // 常规的基础配置(你没写完的部分)
            curl_setopt($ch[$key], CURLOPT_RETURNTRANSFER, true);
            curl_multi_add_handle($mh, $ch[$key]);
        }

        // 常见的执行循环(这部分往往是效率瓶颈)
        $running = null;
        do {
            curl_multi_exec($mh, $running);
        } while ($running > 0);

        // 收集结果并清理资源
        foreach($urls as $key => $value){
            $status[$key] = curl_getinfo($ch[$key], CURLINFO_HTTP_CODE);
            curl_multi_remove_handle($mh, $ch[$key]);
            curl_close($ch[$key]);
        }
        curl_multi_close($mh);
        return $status;
    }
}

核心优化方向

1. 砍掉curl请求的冗余操作

很多时候慢不是curl_multi的锅,而是每个请求做了太多无用功:

  • 设置CURLOPT_NOBODY => true:只获取HTTP头信息,不用下载响应体,直接省掉带宽和响应解析的时间
  • 严格设置超时:CURLOPT_CONNECTTIMEOUT => 3(连接超时3秒)、CURLOPT_TIMEOUT => 5(总请求超时5秒),避免单个慢请求拖垮整个批次
  • 禁用不需要的功能:比如CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1(非必要不用HTTP2),测试/内部场景下可以关掉SSL验证(CURLOPT_SSL_VERIFYPEER => false、CURLOPT_SSL_VERIFYHOST => false)

2. 优化curl_multi的执行循环

你原来的do-while是空轮询,会疯狂占用CPU资源,导致整体效率下降。换成curl_multi_select等待活动连接,减少CPU空转:

$running = null;
do {
    // 等待1秒,有活动连接就继续执行
    $fd = curl_multi_select($mh, 1);
    if ($fd === -1) {
        usleep(1000); // 极端场景下避免CPU跑满
        continue;
    }
    curl_multi_exec($mh, $running);
} while ($running > 0);

3. 控制并发数,避免资源耗尽

一下子扔几百上千个请求,服务器的文件句柄、网络连接都会被占满,反而变慢。建议把并发数控制在50-100之间(根据服务器配置调整):

$maxConcurrent = 50;
$activeHandles = [];
$mh = curl_multi_init();

foreach ($urls as $key => $url) {
    $ch = curl_init($url);
    // 套上前面说的优化配置
    curl_setopt($ch, CURLOPT_NOBODY, true);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3);
    curl_setopt($ch, CURLOPT_TIMEOUT, 5);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_multi_add_handle($mh, $ch);
    $activeHandles[$key] = $ch;

    // 达到最大并发时先处理一批
    if (count($activeHandles) >= $maxConcurrent) {
        do {
            $fd = curl_multi_select($mh, 1);
            if ($fd === -1) {
                usleep(1000);
                continue;
            }
            curl_multi_exec($mh, $running);
        } while ($running > 0);

        // 清理已完成的请求
        foreach ($activeHandles as $k => $handle) {
            $status[$k] = curl_getinfo($handle, CURLINFO_HTTP_CODE);
            curl_multi_remove_handle($mh, $handle);
            curl_close($handle);
        }
        $activeHandles = [];
    }
}

// 处理剩余的请求
do {
    $fd = curl_multi_select($mh, 1);
    if ($fd === -1) {
        usleep(1000);
        continue;
    }
    curl_multi_exec($mh, $running);
} while ($running > 0);

foreach ($activeHandles as $k => $handle) {
    $status[$k] = curl_getinfo($handle, CURLINFO_HTTP_CODE);
    curl_multi_remove_handle($mh, $handle);
    curl_close($handle);
}
curl_multi_close($mh);

4. 复用连接池,减少TCP握手开销

启用TCP连接复用,相同域名的请求可以复用已建立的连接,省掉三次握手的时间:

// 初始化连接共享池
$share = curl_share_init();
curl_share_setopt($share, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT);

// 给每个curl句柄绑定共享池
curl_setopt($ch, CURLOPT_SHARE, $share);

5. 其他小细节优化

  • 提前过滤无效URL:去掉空值、格式错误的URL,避免无效请求浪费资源
  • 只获取需要的信息:用curl_getinfo只取CURLINFO_HTTP_CODE,不要获取整个info数组
  • 延迟非必要操作:比如数据库写入、日志记录,放到所有请求完成后统一处理,不要在循环里穿插

把这些优化点整合进去,你的批量域名检测速度应该能提升好几倍——核心就是减少单个请求的开销、优化curl_multi的执行逻辑、合理控制并发,以及复用连接资源。

内容的提问来源于stack exchange,提问作者M.D

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:35:23