You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何使用CURL发起大量请求且不占用全部CPU资源?

Hey there! 你遇到的CPU占满问题其实挺常见的,尤其是用循环串行发送大量CURL请求的时候。咱们一步步来分析和解决:

问题根源

你的代码功能正常但占满CPU,核心原因主要有两个:

  1. 同步串行请求的密集执行:300次请求挨个跑,PHP进程持续处于高负载状态,CPU几乎被循环和CURL的IO逻辑占满,没有空闲时间。
  2. 如果循环内重复初始化CURL句柄(虽然你的代码片段里是初始化一次,但如果实际业务中每次循环都调用curl_init()),会额外增加资源创建/销毁的开销,进一步拉高CPU占用。

解决方案

1. 复用CURL句柄(必做基础优化)

确保只初始化一次CURL句柄,循环里仅修改POST数据并重复执行请求,这样能大幅减少资源开销。调整后的代码示例:

// 初始化CURL句柄,放在循环外部!
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "websiteURL");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_HEADER, FALSE);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
    "Content-Type: application/json",
    'Authorization: Basic '. base64_encode("XXXXX:YYYYYY")
));
// 可选:开启信号优化+设置超时,减少CPU浪费
curl_setopt($ch, CURLOPT_NOSIGNAL, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($ch, CURLOPT_TIMEOUT, 10);

// 循环发送300条消息
for ($i = 0; $i < 300; $i++) {
    // 构造本次请求的POST数据
    $postData = json_encode(["message" => "你的消息内容 $i"]);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
    
    // 执行请求
    $response = curl_exec($ch);
    
    // 可选:处理请求错误
    if ($response === FALSE) {
        error_log('Curl请求失败: ' . curl_error($ch));
    }
}

// 最后记得关闭句柄
curl_close($ch);

2. 加入短延迟,给CPU喘息空间

如果请求太密集,哪怕复用了句柄,CPU还是会被占满,可以在每次请求后加个100-200毫秒的延迟:

// 在循环内curl_exec之后添加
usleep(100000); // 100毫秒,单位是微秒(1秒=1000000微秒)

这个小延迟能让CPU处理其他任务,避免持续高负载。

3. 用CURL多线程(批量异步请求,最优解)

对于大量请求,串行执行效率低且CPU占用高,改用CURL Multi Handle并行处理多个请求,能更合理利用CPU资源,同时提升请求速度。示例代码:

// 准备300条请求的POST数据
$postDatas = [];
for ($i = 0; $i < 300; $i++) {
    $postDatas[] = json_encode(["message" => "你的消息内容 $i"]);
}

// 初始化多线程句柄
$mh = curl_multi_init();
$handles = [];

// 创建所有CURL句柄并加入多线程池
foreach ($postDatas as $data) {
    $ch = curl_init("websiteURL");
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
    curl_setopt($ch, CURLOPT_HEADER, FALSE);
    curl_setopt($ch, CURLOPT_POST, TRUE);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        "Content-Type: application/json",
        'Authorization: Basic '. base64_encode("XXXXX:YYYYYY")
    ));
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
    curl_setopt($ch, CURLOPT_NOSIGNAL, 1);
    curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
    curl_setopt($ch, CURLOPT_TIMEOUT, 10);
    
    curl_multi_add_handle($mh, $ch);
    $handles[] = $ch;
}

// 执行并行请求,关键用curl_multi_select避免空循环占CPU
$running = null;
do {
    curl_multi_exec($mh, $running);
    curl_multi_select($mh); // 等待请求完成,释放CPU
} while ($running > 0);

// 处理响应并清理资源
foreach ($handles as $ch) {
    $response = curl_multi_getcontent($ch);
    // 这里可以添加响应处理逻辑
    curl_multi_remove_handle($mh, $ch);
    curl_close($ch);
}

curl_multi_close($mh);

这里的curl_multi_select($mh)是核心,它会让进程进入等待状态,直到有请求完成,不会像串行循环那样空转浪费CPU。

总结

优先尝试复用句柄+加延迟的组合,能快速降低CPU占用;如果需要更高的请求效率,直接改用CURL多线程方案,这是处理大量API请求的最优实践。

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

火山引擎 最新活动