curl_multi_setopt() 函数用于设置cURL多句柄的选项。这些选项控制多句柄的行为,如管道化、连接限制等。
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 |
设置内容长度惩罚大小 | 整数 |
// 初始化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);
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";
}
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);
启用HTTP管道化,允许在同一个连接上发送多个HTTP请求。
0 - 禁用管道化1 - 启用HTTP/1.1管道化2 - 启用HTTP/2多路复用3 - 同时启用HTTP/1.1和HTTP/2设置cURL多句柄可以同时打开的最大连接数。当连接数达到此限制时,新的请求将等待现有连接完成。
设置对单个主机名的最大同时连接数。这有助于避免对单个服务器造成过大的负载。
curl_multi_setopt() 函数需要PHP 5.5.0或更高版本,并且需要cURL 7.16.1或更高版本支持。