PHP 实现高效并发 HTTP 请求:CURL Multi 用法详解

沈亦白
沈亦白
发布时间:2026-10-14| 6人浏览过
原创

在 PHP 开发中,处理大量 HTTP 请求时,传统的串行方式效率极低。利用 cURL 扩展提供的多句柄功能(cURL Multi),可以在一个进程中并发发起多个请求,从而大幅缩短整体响应时间。本文将详细解析基于 curl_multi_init 的并发请求实现原理、核心代码结构及关键参数配置。

为什么使用 cURL Multi?

默认的 curl_exec 是阻塞式的,即必须等待当前请求完全结束后才能发起下一个。对于涉及多个 URL 抓取的场景(如聚合搜索、批量 API 调用),这种串行处理会导致总耗时等于所有请求耗时之和。
cURL Multi 接口允许同时管理多个 cURL 句柄,底层利用非阻塞 I/O 机制,使得这些请求能够并行执行,总耗时仅取决于最慢的那个请求加上少量的调度开销。

准备条件与核心逻辑

要实现并发请求,需要准备以下基础环境:

  1. PHP 环境:确保服务器已启用 cURL 扩展(可通过 phpinfo() 验证)。
  2. 目标 URL 列表:待请求的资源地址数组。
  3. 公共选项设置:定义通用的 HTTP 头、超时时间等配置,以减少重复代码。

第1步:初始化与选项配置

首先定义待请求的 URL 数组和通用的 cURL 选项。合理的用户代理(User-Agent)和编码设置有助于避免被服务端拦截或出现乱码。

<?php
// 定义待请求的 URL 列表
$urls = array(
    'http://www.baidu.com/',
    'http://www.pconline.com.cn/',
    'http://www.163.com/'
);

// 配置通用 cURL 选项
$options = array(
    CURLOPT_RETURNTRANSFER => 1,      // 返回字符串而非直接输出
    CURLOPT_FOLLOWLOCATION => 1,      // 跟随重定向
    CURLOPT_HEADER => false,           // 不输出响应头
    CURLOPT_TIMEOUT => 10,             // 全局超时时间(秒)
    CURLOPT_HTTPHEADER => array(
        'Accept' => 'text/html, application/xhtml+xml,',
        'Accept-Encoding' => 'gzip, deflate',
        'Accept-Language' => 'zh-CN',
        'Connection' => 'Keep-Alive',
        'User-Agent' => 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)',
    ),
);

第2步:创建并发执行函数

核心逻辑封装在 curlMultiRequest 函数中。步骤如下:

  1. 初始化 Multi Handle:调用 curl_multi_init() 创建用于管理多个句柄的资源。
  2. 分配单个句柄:遍历 URL,为每个 URL 调用 curl_init(),并设置 URL 和公共选项,最后通过 curl_multi_add_handle() 加入多句柄管理器。
  3. 执行并发请求:使用循环配合 curl_multi_exec() 检查运行状态,直到所有请求完成($running == 0)。
  4. 获取结果并清理:遍历已完成的句柄,提取内容,移除句柄并关闭连接,最后关闭 Multi Handle。
复制代码 代码如下:
<?php
function curlMultiRequest($urls, $options = array()){
    $ch = array();
    $results = array();
    
    // 1. 初始化 Multi Handle
    $mh = curl_multi_init();
    
    // 2. 添加所有请求到 Multi Handle
    foreach($urls as $key => $val){
        $ch[$key] = curl_init();
        if($options){
            curl_setopt_array($ch[$key], $options);
        }
        curl_setopt($ch[$key], CURLOPT_URL, $val);
        curl_multi_add_handle($mh, $ch[$key]);
    }
    
    // 3. 执行并发请求
    $running = null;
    do {
        // 执行当前批次的操作
        curl_multi_exec($mh, $running);
        // 可选:curl_multi_select($mh) 可提高 CPU 效率,减少空转
    } while ($running > 0);
    
    // 4. 收集结果并清理资源
    foreach($ch as $key => $val){
        // 获取响应内容
        $results[$key] = curl_multi_getcontent($val);
        // 从 Multi Handle 中移除并关闭单个 cURL 句柄
        curl_multi_remove_handle($mh, $val);
        curl_close($val);
    }
    
    // 关闭 Multi Handle
    curl_multi_close($mh);
    
    return $results;
}

// 执行请求
$results = curlMultiRequest($urls, $options);
print_r($results);
?>

关键细节与排错指南

1. 编码转换问题

早期代码中常使用 iconv('gb2312','utf-8', ...) 进行手动编码转换。在现代 PHP 环境中,建议统一使用 UTF-8。如果目标站点返回 GBK 编码,需在接收后进行处理,或直接通过 mb_convert_encoding 解决,以避免因编码不一致导致的页面解析错误。

2. 性能优化建议

在 do-while 循环中,直接调用 curl_multi_exec 会导致一定的 CPU 占用。建议在循环中加入 curl_multi_select($mh, 1.0)。该函数会在没有活动连接时挂起进程一段时间,等待有事件发生时再唤醒,能显著降低 CPU 负载,尤其适合处理大量并发请求。

3. 句柄未正确清理

务必确保在使用完每个单句柄后调用 curl_multi_remove_handle 和 curl_close。若遗漏 curl_multi_close,虽然脚本结束时系统会回收资源,但在长期运行的服务中可能导致内存泄漏。

简要总结

通过上述 curlMultiRequest 函数的封装,开发者可以轻松地在 PHP 中实现高效的并发 HTTP 请求。掌握 curl_multi 系列函数的使用,不仅能提升数据采集的效率,也是构建高性能 Web 应用的基础技能之一。以上就是基于PHP CURL用法的深入分析的详细内容,更多关于PHP并发请求与网络优化的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。