当前位置: 首页> 最新文章列表> 如何在并发请求完成后,优雅地关闭所有 CURL 会话

如何在并发请求完成后,优雅地关闭所有 CURL 会话

gitbox 2025-05-12

在进行大量并发 HTTP 请求时,PHP 提供的 curl_multi_* 系列函数是一个非常实用的工具,能让你在一个脚本中同时发起多个请求,从而提高执行效率。其中,curl_multi_close() 是整个流程中的最后一步,它负责清理 curl_multi_init() 初始化的资源,确保所有的 CURL 句柄被妥善关闭,不留下资源泄露的隐患。本文将通过一个完整的示例,详细讲解如何在所有并发请求完成之后,优雅地关闭所有 CURL 会话。

一、基础概念回顾

在使用 curl_multi_* 进行并发请求时,一般的流程如下:

  1. 初始化一个 curl_multi 容器。

  2. 创建多个 curl 请求,并将其加入 curl_multi 容器。

  3. 使用 curl_multi_exec 驱动所有请求的执行。

  4. 循环检查请求是否完成。

  5. 分别处理每一个 curl 请求的结果。

  6. 移除每一个单独的 curl 句柄。

  7. 使用 curl_multi_close() 释放资源。

二、示例代码讲解

以下是一个示例,演示如何并发请求多个 URL,并在所有请求结束后优雅地关闭资源:

<?php

// 要并发请求的 URL 列表
$urls = [
    "https://gitbox.net/api/data1",
    "https://gitbox.net/api/data2",
    "https://gitbox.net/api/data3"
];

// 初始化 curl_multi 句柄
$multiHandle = curl_multi_init();
$curlHandles = [];

// 为每一个 URL 创建一个单独的 curl 句柄,并加入 multi 句柄
foreach ($urls as $url) {
    $ch = curl_init();
    curl_setopt_array($ch, [
        CURLOPT_URL => $url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT => 10
    ]);
    curl_multi_add_handle($multiHandle, $ch);
    $curlHandles[] = $ch;
}

// 执行所有请求
$active = null;
do {
    $mrc = curl_multi_exec($multiHandle, $active);
    // curl_multi_select 阻塞直到有活动连接
    if ($active) {
        curl_multi_select($multiHandle);
    }
} while ($active && $mrc == CURLM_OK);

// 获取每一个请求的返回结果
foreach ($curlHandles as $ch) {
    $response = curl_multi_getcontent($ch);
    $info = curl_getinfo($ch);
    $error = curl_error($ch);

    echo "URL: " . $info['url'] . PHP_EOL;
    echo "HTTP Code: " . $info['http_code'] . PHP_EOL;
    echo "Response: " . $response . PHP_EOL;
    echo "Error: " . $error . PHP_EOL;
    echo str_repeat("-", 40) . PHP_EOL;

    // 移除并关闭句柄
    curl_multi_remove_handle($multiHandle, $ch);
    curl_close($ch);
}

// 最后,关闭 multi 句柄
curl_multi_close($multiHandle);

?>

三、关于 curl_multi_close 的注意事项

  • 只在所有句柄都被移除后调用:调用 curl_multi_close() 之前,应该先通过 curl_multi_remove_handle() 把所有子句柄从 multi 容器中移除,再逐个调用 curl_close()。否则可能造成资源未释放或行为不确定。

  • 不会自动关闭子句柄curl_multi_close() 只会关闭 multi 容器自身,并不会自动关闭内部的 curl 句柄。你需要手动关闭每一个 curl_init() 创建的句柄。

  • 调用时机curl_multi_close() 应该是你整个流程中最后执行的步骤。它的调用标志着整个并发请求生命周期的正式结束。

四、总结

通过合理使用 curl_multi_init()curl_multi_close(),你可以在 PHP 中高效地进行并发网络请求,同时确保资源在使用完毕后被正确释放,避免内存泄漏或连接异常。务必记住:每一个 curl_init() 对应一个 curl_close(),每一个 curl_multi_init() 对应一个 curl_multi_close(),这样才能让你的代码更加健壮和可靠。