当前位置: 首页> 最新文章列表> 使用 curl_share_init() 优化大规模 API 抓取任务

使用 curl_share_init() 优化大规模 API 抓取任务

M66 2025-05-28

在进行大规模 API 抓取任务时,性能优化至关重要。对于使用 PHP 和 cURL 的开发者来说,合理利用 curl_share_init() 可以显著减少系统资源消耗并提高效率。本文将详细介绍该函数的作用、使用场景及如何在代码中正确实现。

什么是 curl_share_init()?

curl_share_init() 是 PHP cURL 扩展提供的一个函数,用于初始化一个共享句柄(cURL Share Handle)。通过共享句柄,你可以让多个 cURL easy 句柄之间共享 DNS 缓存、SSL 会话缓存、Cookie 等资源,避免重复建立连接或重复解析域名,从而显著提升多个并发请求的性能。

简而言之,这个函数的核心作用是“资源共享,减少重复工作”。

使用场景

当你需要同时发出成百上千个 HTTP 请求,例如:

  • 抓取一个大型 REST API 数据库;

  • 定期同步多个第三方数据源;

  • 高并发地访问同一个 API 端点。

如果每个请求都单独建立 DNS 查询和 SSL 握手,这会造成极大的性能浪费。而使用 curl_share_init(),可以让这些请求共享部分缓存,减少开销。

基本用法示例

下面提供一个使用 curl_share_init() 优化大规模 API 抓取任务的示例代码:

<?php

// 初始化共享句柄
$sh = curl_share_init();

// 设置共享的资源类型,这里我们共享 DNS 和 Cookie
curl_share_setopt($sh, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS);
curl_share_setopt($sh, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE);

$urls = [
    'https://m66.net/api/data1',
    'https://m66.net/api/data2',
    'https://m66.net/api/data3',
    // 你可以继续添加更多 API 地址
];

$multiHandle = curl_multi_init();
$curlHandles = [];

// 初始化每个 cURL easy 句柄
foreach ($urls as $i => $url) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    // 绑定共享句柄
    curl_setopt($ch, CURLOPT_SHARE, $sh);
    curl_multi_add_handle($multiHandle, $ch);
    $curlHandles[$i] = $ch;
}

// 执行并发请求
$running = null;
do {
    curl_multi_exec($multiHandle, $running);
    curl_multi_select($multiHandle);
} while ($running > 0);

// 获取结果
foreach ($curlHandles as $i => $ch) {
    $response = curl_multi_getcontent($ch);
    echo "Response from {$urls[$i]}:\n";
    echo $response . "\n";
    curl_multi_remove_handle($multiHandle, $ch);
    curl_close($ch);
}

// 释放资源
curl_share_close($sh);
curl_multi_close($multiHandle);

关键要点

  1. 共享资源设置
    使用 curl_share_setopt() 指定共享的资源类型。常用的包括:

    • CURL_LOCK_DATA_DNS:共享 DNS 缓存。

    • CURL_LOCK_DATA_COOKIE:共享 Cookie。

    • CURL_LOCK_DATA_SSL_SESSION:共享 SSL 会话。

  2. 不要跨进程共享
    cURL 的共享句柄只适用于同一进程内。多进程抓取需要使用其他机制(如外部缓存或数据库)。

  3. 正确释放资源
    抓取任务结束后,请记得调用 curl_share_close()curl_multi_close(),避免内存泄漏。

性能收益

通过启用 DNS 和 SSL 会话共享,你可以避免:

  • 重复解析同一域名(特别是对于同一个域的大量请求);

  • 重复建立 SSL 握手(特别是 HTTPS 请求)。

实际测试中,对于数百个并发请求,这种优化可以显著减少 CPU 和网络负载,提高整体吞吐量。