使用curl_multi_exec并发请求外部接口
有时候在一个PHP方法中要多次调用外部的接口,为了优化代码,提高效率,我们不妨使用curl_multi_exec并发处理多个请求,这样可以明显地提高获取响应数据的速度,减少程序执行的时间,下面是一个实际运行的例子。
<?php
/**
* 使用curl并行发送多个请求获取数据
* @param array $urls 多个请求数组
* @return array
*/
function sendMulti_request(array $urls)
{
$conn = [];
$res = [];
//创建批处理curl句柄
$mh = curl_multi_init();
foreach ($urls as $k => $item) {
$conn[$k] = curl_init(); //初始化各个子连接
//设置url和相应的选项
curl_setopt($conn[$k], CURLOPT_URL, $item['url']);
curl_setopt($conn[$k], CURLOPT_HEADER, 0);
curl_setopt($conn[$k], CURLOPT_RETURNTRANSFER, 1); //不直接输出到浏览器,而是返回字符串
curl_setopt($conn[$k], CURLOPT_TIMEOUT, 10);
if ($item['method'] == 'post') {
curl_setopt( $conn[$k], CURLOPT_POST, true );
$params = $item['params'];
if (is_array($item['params'])) {
$flag = true;
foreach ($params as $key => $val) {
if (strpos($val, '@') === 0) {
$flag = false;
break;
}
}
if ($flag) {
$params = http_build_query($params);
}
}
curl_setopt($conn[$k], CURLOPT_POSTFIELDS, $params);
}
//处理302跳转
curl_setopt($conn[$k], CURLOPT_FOLLOWLOCATION, 1);
//增加句柄
curl_multi_add_handle($mh, $conn[$k]); //加入多处理句柄
}
$active = 0; //连接数
//防卡死写法:执行批处理句柄
do {
$mrc = curl_multi_exec($mh, $active);
//这个循环的目的是尽可能地读写,直到无法继续读写为止
//返回 CURLM_CALL_MULTI_PERFORM 表示还能继续向网络读写
} while($mrc == CURLM_CALL_MULTI_PERFORM);
/*var_dump($mrc);
echo '<hr/>';
var_dump($active);die;*/
while ($active && $mrc == CURLM_OK) {
if (curl_multi_select($mh) != -1) {
do {
$mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
}
}
foreach ($urls as $k => $url) {
$info = curl_multi_info_read($mh);
// var_dump($info);
$headers = curl_getinfo($conn[$k]);
// var_dump($headers);
$res[$k] = curl_multi_getcontent($conn[$k]);
//移除curl批处理句柄资源中的某一个句柄资源
curl_multi_remove_handle($mh, $conn[$k]);
//关闭curl会话
curl_close($conn[$k]);
}
//关闭全部句柄
curl_multi_close($mh);
return $res;
}
//$list是我们组装的请求实体,这个可以自行设置
/*定义我们请求的数据和地址*/
foreach ($list as $k=>$v){
$parameters[$k]['url'] = $v['url'];
$parameters[$k]['params'] = $v['param'];
$parameters[$k]['method'] = 'post';
}
$row = sendMulti_request($parameters);
不要着急,是不是发现用不了 主要这个两个地方,1、代码整理完之后要放到服务器上去访问 2、请求的url 也要是公网可以访问的