当前位置: 首页> 最新文章列表> curl_multi_close 与 curl_multi_init 的正确顺序使用

curl_multi_close 与 curl_multi_init 的正确顺序使用

gitbox 2025-05-12

在PHP中,cURL 是一个强大且常用的网络请求工具,而 curl_multi_* 系列函数允许我们。这在进行高性能接口聚合、异步请求等场景中非常有用。

然而,许多开发者在使用 curl_multi_* 时,常常忽略了资源的释放环节,尤其是 curl_multi_close() 的使用。本文将以标准流程为主线,带你一步步理解从 curl_multi_initcurl_multi_close 的完整使用方式,并辅以代码示例说明。

一、什么是 curl_multi 系列函数?

PHP 提供的 curl_multi_* 系列函数是用于管理多个并发 curl 句柄的工具。这与传统的单个 curl 请求不同,它允许你同时发起多个 HTTP 请求,提升响应效率。

使用这些函数可以大致分为以下几个步骤:

  1. 初始化 multi 句柄:curl_multi_init()

  2. 添加多个 curl 请求(easy handle):curl_multi_add_handle()

  3. 执行请求:curl_multi_exec()curl_multi_select()

  4. 获取响应内容:curl_multi_getcontent()

  5. 移除并关闭 easy handle:curl_multi_remove_handle()curl_close()

  6. 关闭 multi handle:curl_multi_close()

二、标准流程讲解及代码示例

下面是一个标准的多请求流程,假设我们需要并发请求三个不同的 URL:

<?php

// 要请求的 URL 列表
$urls = [
    "https://gitbox.net/api/service1",
    "https://gitbox.net/api/service2",
    "https://gitbox.net/api/service3"
];

// 初始化 multi handle
$multiHandle = curl_multi_init();
$curlHandles = [];

// 1. 为每个 URL 创建一个 curl easy handle 并添加到 multi handle 中
foreach ($urls as $i => $url) {
    $ch = curl_init();

    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    curl_multi_add_handle($multiHandle, $ch);
    $curlHandles[$i] = $ch;
}

// 2. 执行 multi 请求
$active = null;
do {
    $mrc = curl_multi_exec($multiHandle, $active);
    // 等待网络 I/O 准备好,避免 CPU 占用过高
    if ($mrc == CURLM_OK) {
        curl_multi_select($multiHandle);
    }
} while ($active > 0 && $mrc == CURLM_OK);

// 3. 获取内容并清理句柄
$responses = [];
foreach ($curlHandles as $i => $ch) {
    // 获取响应内容
    $responses[$i] = curl_multi_getcontent($ch);

    // 移除并关闭单个 handle
    curl_multi_remove_handle($multiHandle, $ch);
    curl_close($ch);
}

// 4. 最后关闭 multi handle,释放资源
curl_multi_close($multiHandle);

// 输出结果
foreach ($responses as $index => $body) {
    echo "Response from URL #{$index}: \n";
    echo $body . "\n\n";
}

三、为什么 curl_multi_close 很重要?

虽然 curl_multi_close() 并不会立即销毁 easy handle(你需要先移除再关闭它们),但它负责释放 multi handle 本身占用的底层资源。如果你忘记调用它,在长时间运行的脚本(如常驻进程)中可能导致内存泄漏或者文件描述符耗尽的问题。

总结:任何使用了 curl_multi_init() 的脚本,必须以 curl_multi_close() 结尾!

四、常见问题排查建议

  1. 请求阻塞卡住?

    • 检查是否正确使用了 curl_multi_select()

    • 确保没有漏掉 curl_setopt(..., CURLOPT_RETURNTRANSFER, true)

  2. 内存泄露或连接异常?

五、总结

在并发处理网络请求时,curl_multi_* 提供了非常高效的手段。掌握从 curl_multi_init()curl_multi_close() 的完整流程,能有效提高代码性能和资源管理能力。

记住这三个“必须”:

  • 每个请求都必须添加到 multi 句柄中;

  • 每个请求都必须在完成后被移除和关闭;

  • 最终必须调用 curl_multi_close() 来释放 multi 资源。

通过规范的流程和资源管理,你的 PHP 并发请求将更加健壮和高效。