PHP 多线程 curl_multi_init 的使用 PK curl_init 看看那个更快
php中可以通过CURL处理HTTP请求,其中curl_init()是单线程模式,如果需要对事务处理走多线程模式,那么就需要用到curl_multi_init()函数。
本案例用来测试大并发的情况下 curl_multi_init() 到底比 curl_init() 快多少。
话不多少,直接上代码:
<?php
class Http
{
/**
* https 发起post请求
* @param string $url url信息
* @param mixed $data 参数信息[$data = '{"a":1,"b":2}' or $data = array("a" => 1,"b" => 2)]
* @param int $timeOut 超时设置
* @param string $proxyHost 代理host
* @param int $proxyPort 代理端口
* @return string
*/
public static function post($url, $data = null, $timeOut = 20, $proxyHost = null, $proxyPort = null)
{
try {
if (strlen($url) < 1) {
return null;
}
$ch = curl_init();
// 设置url
curl_setopt($ch, CURLOPT_URL, $url);
if (false == empty($data)) {
curl_setopt($ch, CURLOPT_POST, 1);
if (is_array($data) && count($data) > 0) {
curl_setopt($ch, CURLOPT_POST, count($data));
}
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
}
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
// 如果成功只将结果返回,不自动输出返回的内容
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// user-agent
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:22.0) Gecko/20100101 Firefox/22.0");
// 超时
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeOut);
// 使用代理
if (strlen($proxyHost) > 0 && strlen($proxyPort) > 0) {
// 代理认证模式
curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_BASIC);
// 代理服务器地址
curl_setopt($ch, CURLOPT_PROXY, $proxyHost);
// 代理服务器端口
curl_setopt($ch, CURLOPT_PROXYPORT, $proxyPort);
// 使用http代理模式
curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
}
// 执行
$out = curl_exec($ch);
// 关闭
curl_close($ch);
return $out;
} catch (Exception $e) {
return null;
}
}
/**
* https 发起post多发请求
* @param array $nodes url和参数信息。
* $nodes = [
* [0] = > [
* 'url' => 'http://www.baidu.com',
* 'data' => '{"a":1,"b":2}'
* ],
* [1] = > [
* 'url' => 'http://www.baidu.com',
* 'data' => null
* ]
* ....
* ];
* @param int $timeOut 超时设置
* @return array
*/
public static function postMulti($nodes, $timeOut = 5)
{
try {
if (false == is_array($nodes)) {
return array();
}
$mh = curl_multi_init();
$curlArray = array();
foreach ($nodes as $key => $info) {
if (false == is_array($info)) {
continue;
}
if (false == isset($info['url'])) {
continue;
}
$ch = curl_init();
// 设置url
$url = $info['url'];
curl_setopt($ch, CURLOPT_URL, $url);
$data = isset($info['data']) ? $info['data'] : null;
if (false == empty($data)) {
curl_setopt($ch, CURLOPT_POST, 1);
// array
if (is_array($data) && count($data) > 0) {
curl_setopt($ch, CURLOPT_POST, count($data));
}
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
}
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
// 如果成功只将结果返回,不自动输出返回的内容
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// user-agent
curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows NT 6.2; WOW64; rv:22.0) Gecko/20100101 Firefox/22.0");
// 超时
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeOut);
$curlArray[$key] = $ch;
curl_multi_add_handle($mh, $curlArray[$key]);
}
$running = NULL;
do {
usleep(10000);
curl_multi_exec($mh, $running);
} while ($running > 0);
$res = array();
foreach ($nodes as $key => $info) {
$res[$key] = curl_multi_getcontent($curlArray[$key]);
}
foreach ($nodes as $key => $info) {
curl_multi_remove_handle($mh, $curlArray[$key]);
}
curl_multi_close($mh);
return $res;
} catch (Exception $e) {
return array();
}
}
}
$count = 10;
//2.1 循环调用Http::post() 100次
$url = 'https://api.weixin.qq.com/cgi-bin/getcallbackip?access_token=abcdasdfasdfasdfasdfasdfasdfasdfasdfasdf';
$startTime = microtime(true);
for ($i = 1; $i <= $count; $i++) {
$res = Http::post($url);
}
$endTime = microtime(true);
echo $endTime - $startTime;
echo "\n";
//2.2 调用Http::postMulti()一次发100个url
$url = 'https://api.weixin.qq.com/cgi-bin/getcallbackip?access_token=abcdasdfasdfasdfasdfasdfasdfasdfasdfasdf';
$nodes = array();
for ($i = 1; $i <= $count; $i++) {
$info = array();
$info['url'] = $url;
$nodes[] = $info;
}
$startTime = microtime(true);
$res = Http::postMulti($nodes);
$endTime = microtime(true);
echo $endTime - $startTime;
echo "\n";
?>运行结果:
* 当$count=10的情况下,耗时分别为:
3.41195106506350.44486904144287
curl_multi_init() 比 curl_init() 快了8倍。
* 当 $count=100的情况下,耗时分别为:
34.1900150775911.9350771903992
curl_multi_init() 比 curl_init() 快了17倍。



