PHP curl_multi_setopt函数

定义和用法

curl_multi_setopt() 函数用于设置cURL多句柄的选项。这些选项控制多句柄的行为,如管道化、连接限制等。

注意:此函数在PHP 5.5.0及以上版本可用。

语法

curl_multi_setopt ( CurlMultiHandle $multi_handle , int $option , mixed $value ) : bool

参数

参数 描述
multi_handle curl_multi_init() 返回的 cURL 多句柄。
option 要设置的选项常量(参见下面的选项表)。
value 要为选项设置的值。

返回值

成功时返回 true,失败时返回 false

可用选项

选项 描述 值类型
CURLMOPT_PIPELINING 启用或禁用HTTP管道化 整数
CURLMOPT_MAXCONNECTS 设置最大同时连接数 整数
CURLMOPT_MAX_HOST_CONNECTIONS 设置单个主机的最大连接数 整数
CURLMOPT_MAX_PIPELINE_LENGTH 设置管道的最大请求数 整数
CURLMOPT_MAX_TOTAL_CONNECTIONS 设置最大总连接数 整数
CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE 设置块长度惩罚大小 整数
CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE 设置内容长度惩罚大小 整数

示例

示例 1:基本用法 - 设置连接限制

// 初始化cURL多句柄
$mh = curl_multi_init();

// 设置多句柄选项
curl_multi_setopt($mh, CURLMOPT_MAXCONNECTS, 10);           // 最大同时连接数
curl_multi_setopt($mh, CURLMOPT_MAX_HOST_CONNECTIONS, 2);   // 每个主机最大连接数

// 创建多个cURL句柄
$urls = [
    'http://api.example.com/users',
    'http://api.example.com/products',
    'http://api.example.com/orders',
    'http://another-api.com/data'
];

$handles = [];
foreach ($urls as $url) {
    $ch = curl_init();
    curl_setopt_array($ch, [
        CURLOPT_URL => $url,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT => 30
    ]);
    curl_multi_add_handle($mh, $ch);
    $handles[] = $ch;
}

// 执行并发请求
$active = null;
do {
    $mrc = curl_multi_exec($mh, $active);
    if ($mrc != CURLM_OK) {
        break;
    }
    curl_multi_select($mh);
} while ($active);

// 处理结果并清理
foreach ($handles as $ch) {
    $content = curl_multi_getcontent($ch);
    echo "获取内容长度: " . strlen($content) . "\n";
    curl_multi_remove_handle($mh, $ch);
    curl_close($ch);
}

curl_multi_close($mh);

示例 2:启用HTTP管道化

function pipelinedRequests($urls) {
    $mh = curl_multi_init();

    // 启用HTTP管道化
    curl_multi_setopt($mh, CURLMOPT_PIPELINING, 1);
    curl_multi_setopt($mh, CURLMOPT_MAX_PIPELINE_LENGTH, 5);

    $handles = [];
    foreach ($urls as $index => $url) {
        $ch = curl_init();
        curl_setopt_array($ch, [
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
            CURLOPT_TIMEOUT => 30
        ]);
        curl_multi_add_handle($mh, $ch);
        $handles[$index] = $ch;
    }

    $active = null;
    $results = [];

    do {
        $status = curl_multi_exec($mh, $active);
        if ($active) {
            curl_multi_select($mh, 0.1);
        }
    } while ($active && $status == CURLM_OK);

    // 收集结果
    foreach ($handles as $index => $ch) {
        $results[$index] = [
            'content' => curl_multi_getcontent($ch),
            'http_code' => curl_getinfo($ch, CURLINFO_HTTP_CODE),
            'error' => curl_error($ch)
        ];
        curl_multi_remove_handle($mh, $ch);
        curl_close($ch);
    }

    curl_multi_close($mh);
    return $results;
}

// 使用示例
$urls = [
    'http://httpbin.org/get?page=1',
    'http://httpbin.org/get?page=2',
    'http://httpbin.org/get?page=3',
    'http://httpbin.org/get?page=4',
    'http://httpbin.org/get?page=5'
];

$results = pipelinedRequests($urls);
foreach ($results as $index => $result) {
    echo "请求 {$index}: HTTP {$result['http_code']}, 错误: {$result['error']}\n";
}

示例 3:高级连接管理

function optimizedConcurrentRequests($urls) {
    $mh = curl_multi_init();

    // 设置优化的多句柄选项
    curl_multi_setopt($mh, CURLMOPT_MAXCONNECTS, 8);           // 最大8个同时连接
    curl_multi_setopt($mh, CURLMOPT_MAX_HOST_CONNECTIONS, 3);  // 每个主机最多3个连接
    curl_multi_setopt($mh, CURLMOPT_MAX_TOTAL_CONNECTIONS, 15); // 总连接数限制

    // 启用管道化以提升性能
    curl_multi_setopt($mh, CURLMOPT_PIPELINING, CURLPIPE_HTTP1 | CURLPIPE_MULTIPLEX);

    $handles = [];
    $startTime = microtime(true);

    foreach ($urls as $url) {
        $ch = curl_init();
        curl_setopt_array($ch, [
            CURLOPT_URL => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => 60,
            CURLOPT_CONNECTTIMEOUT => 10,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_USERAGENT => 'Mozilla/5.0 (compatible; PHP cURL)'
        ]);

        curl_multi_add_handle($mh, $ch);
        $handles[] = $ch;
    }

    echo "开始执行 " . count($handles) . " 个并发请求...\n";

    // 执行请求
    $active = null;
    do {
        $status = curl_multi_exec($mh, $active);
        if ($status == CURLM_OK && $active) {
            // 等待活动,避免忙等待
            if (curl_multi_select($mh, 0.5) == -1) {
                usleep(10000); // 10毫秒
            }
        }
    } while ($active && $status == CURLM_OK);

    $endTime = microtime(true);
    $executionTime = $endTime - $startTime;

    echo "所有请求完成,耗时: " . round($executionTime, 2) . " 秒\n";

    // 处理结果
    $successCount = 0;
    foreach ($handles as $ch) {
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        if ($httpCode >= 200 && $httpCode < 300) {
            $successCount++;
        }
        curl_multi_remove_handle($mh, $ch);
        curl_close($ch);
    }

    curl_multi_close($mh);

    echo "成功请求: {$successCount}/" . count($handles) . "\n";
    return $successCount;
}

// 使用示例
$urls = array_fill(0, 20, 'http://httpbin.org/delay/1'); // 模拟延迟1秒的请求
optimizedConcurrentRequests($urls);

选项详解

CURLMOPT_PIPELINING

启用HTTP管道化,允许在同一个连接上发送多个HTTP请求。

  • 0 - 禁用管道化
  • 1 - 启用HTTP/1.1管道化
  • 2 - 启用HTTP/2多路复用
  • 3 - 同时启用HTTP/1.1和HTTP/2

CURLMOPT_MAXCONNECTS

设置cURL多句柄可以同时打开的最大连接数。当连接数达到此限制时,新的请求将等待现有连接完成。

CURLMOPT_MAX_HOST_CONNECTIONS

设置对单个主机名的最大同时连接数。这有助于避免对单个服务器造成过大的负载。

注意事项

版本兼容性:curl_multi_setopt() 函数需要PHP 5.5.0或更高版本,并且需要cURL 7.16.1或更高版本支持。
性能提示:合理设置连接限制和启用管道化可以显著提升并发请求的性能,特别是在处理大量请求时。

相关函数