PHP curl_multi_close 函数
最后修改日期:2025 年 4 月 11 日
PHP 的 curl_multi_close
函数用于关闭一组 cURL 句柄。它用于在同时执行多个 cURL 请求后清理资源。此函数是 PHP cURL 多接口的一部分。
基本定义
curl_multi_close
函数关闭一个 cURL 多句柄并释放所有关联的资源。它以一个由 curl_multi_init()
创建的 cURL 多句柄作为其唯一参数。
语法:curl_multi_close(CurlMultiHandle $multi_handle): void
。调用此函数后,多句柄将无法再使用。务必在使用完毕后关闭多句柄,以防止内存泄漏。
基础多请求
此示例演示了如何进行多个请求并关闭句柄。
basic_multi.php
<?php declare(strict_types=1); $urls = [ "https://jsonplaceholder.typicode.com/posts/1", "https://jsonplaceholder.typicode.com/posts/2", "https://jsonplaceholder.typicode.com/posts/3" ]; $mh = curl_multi_init(); $handles = []; foreach ($urls as $url) { $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_multi_add_handle($mh, $ch); $handles[] = $ch; } do { $status = curl_multi_exec($mh, $active); if ($active) { curl_multi_select($mh); } } while ($active && $status == CURLM_OK); foreach ($handles as $ch) { echo curl_multi_getcontent($ch) . "\n"; curl_multi_remove_handle($mh, $ch); curl_close($ch); } curl_multi_close($mh);
此代码同时获取三个帖子。我们创建单独的句柄,将它们添加到多句柄中,然后执行它们。获取内容后,我们会妥善清理所有资源。
多请求中的错误处理
此示例展示了多 cURL 请求的错误处理。
error_handling.php
<?php declare(strict_types=1); $urls = [ "https://jsonplaceholder.typicode.com/posts/1", "https://invalid.url", "https://jsonplaceholder.typicode.com/posts/3" ]; $mh = curl_multi_init(); $handles = []; foreach ($urls as $url) { $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT, 10); curl_multi_add_handle($mh, $ch); $handles[$url] = $ch; } do { $status = curl_multi_exec($mh, $active); if ($active) { curl_multi_select($mh); } } while ($active && $status == CURLM_OK); foreach ($handles as $url => $ch) { if (curl_errno($ch)) { echo "Error for $url: " . curl_error($ch) . "\n"; } else { echo "Success for $url\n"; } curl_multi_remove_handle($mh, $ch); curl_close($ch); } curl_multi_close($mh);
我们故意包含一个无效 URL 来演示错误处理。每个句柄在执行后都会进行错误检查。在处理完所有请求后,多句柄会被妥善关闭。
并行 API 请求
此示例展示了如何并行从多个 API 获取数据。
parallel_apis.php
<?php declare(strict_types=1); $apis = [ "users" => "https://jsonplaceholder.typicode.com/users/1", "posts" => "https://jsonplaceholder.typicode.com/posts/1", "comments" => "https://jsonplaceholder.typicode.com/comments/1" ]; $mh = curl_multi_init(); $handles = []; foreach ($apis as $name => $url) { $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_multi_add_handle($mh, $ch); $handles[$name] = $ch; } do { $status = curl_multi_exec($mh, $active); if ($active) { curl_multi_select($mh); } } while ($active && $status == CURLM_OK); $results = []; foreach ($handles as $name => $ch) { $results[$name] = json_decode(curl_multi_getcontent($ch), true); curl_multi_remove_handle($mh, $ch); curl_close($ch); } curl_multi_close($mh); print_r($results);
我们同时从三个不同的 API 端点获取数据。结果存储在一个关联数组中,并带有有意义的键。处理完响应后,所有句柄都会被妥善清理。
为多请求设置自定义标头
此示例演示了为多个请求设置自定义标头。
multi_headers.php
<?php declare(strict_types=1); $urls = [ "https://api.example.com/resource1", "https://api.example.com/resource2" ]; $headers = [ 'Authorization: Bearer abc123', 'Content-Type: application/json' ]; $mh = curl_multi_init(); $handles = []; foreach ($urls as $url) { $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_multi_add_handle($mh, $ch); $handles[] = $ch; } do { $status = curl_multi_exec($mh, $active); if ($active) { curl_multi_select($mh); } } while ($active && $status == CURLM_OK); foreach ($handles as $ch) { echo curl_multi_getcontent($ch) . "\n"; curl_multi_remove_handle($mh, $ch); curl_close($ch); } curl_multi_close($mh);
我们在多句柄中的所有请求上设置了相同的自定义标头。标头包括授权和内容类型。处理后,我们会妥善清理所有 cURL 资源。
性能比较:顺序 vs 并行
此示例比较了顺序和并行请求的执行。
performance.php
<?php declare(strict_types=1); $urls = array_fill(0, 5, "https://jsonplaceholder.typicode.com/posts/1"); // Sequential requests $start = microtime(true); foreach ($urls as $url) { $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_exec($ch); curl_close($ch); } $sequential = microtime(true) - $start; // Parallel requests $start = microtime(true); $mh = curl_multi_init(); $handles = []; foreach ($urls as $url) { $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_multi_add_handle($mh, $ch); $handles[] = $ch; } do { $status = curl_multi_exec($mh, $active); if ($active) { curl_multi_select($mh); } } while ($active && $status == CURLM_OK); foreach ($handles as $ch) { curl_multi_remove_handle($mh, $ch); curl_close($ch); } curl_multi_close($mh); $parallel = microtime(true) - $start; echo "Sequential: " . $sequential . " seconds\n"; echo "Parallel: " . $parallel . " seconds\n";
此代码演示了并行请求的性能优势。我们测量了两种方法的执行时间。并行执行完成后,多句柄会被妥善关闭。
最佳实践
- 资源清理: 务必使用 curl_multi_close 关闭多句柄。
- 错误处理: 执行后检查各个句柄的错误。
- 内存管理: 使用完毕后从多句柄中移除句柄。
- 超时: 为各个句柄设置 CURLOPT_TIMEOUT。
- 并发: 限制同时发起的请求数量。
来源
本教程涵盖了 PHP 的 curl_multi_close
函数,并通过实际示例展示了其在并行 HTTP 请求场景中的用法。