PHP中CURL_MULTI的使用方法简单示例
2013-05-27 13:37
1241 查看
0)主要给出了一个php中使用curl_multi,也就是curl批处理地一个示例,并解释了一下为什么需要这么做;最后,针对官方示例的不足,做了一点小小的改进,可以在每完成一个请求后立刻就对该请求返回的内容进行处理。
关键字:php ,curl, curl_multi, curl批处理, BigPipe, curl 并发请求
1)php文档中,curl_multi这一块只有几个函数的形式化说明,和几个没有任何文档的例子。要想细致的了解其用法,就需要查一些curl库的资料,或者看一下其他人的使用心得。最近整理了一下,记在这里,防止以后遗忘。
curl_multi的基本流程如下:
<?php
//curl_multi的初始化过程,需要把curl加入到curl_multi中作为handle
$connomains = array(
"http://www.cnn.com/",
"http://www.canada.com/",
"http://www.yahoo.com/",
"http://www.baidu.com/"
);
$mh = curl_multi_init();
foreach ($connomains as $i => $url) {
$conn[$i]=curl_init($url);
curl_setopt($conn[$i],CURLOPT_RETURNTRANSFER,1);
curl_multi_add_handle ($mh,$conn[$i]);
}
//下面这11行是实际的请求过程,curl_multi_select是为了避免curl_multi_exec死循环占据了所有的cpu资源。
$active = null;
do {
$mrc = curl_multi_exec($mh,$active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
while ($active and $mrc == CURLM_OK) {
if (curl_multi_select($mh) != -1) {
do {
$mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
}
}
//下面是curl的清理过程
foreach ($connomains as $i => $url) {
//获取curl获取到的内容
$res[$i]=curl_multi_getcontent($conn[$i]);
curl_close($conn[$i]);
curl_multi_remove_handle($mh, $conn[$i]);
}
curl_multi_close($mh);
print_r($res);
curl_multi执行过程中,包含了两个主要的循环。一个do-while循环不停的调用curl_multi_exec函数,这个函数是不阻塞的,它执行后返回状态码,如果状态码是CURLM_CALL_MULTI_PERFORM,说明还有工作需要立刻执行,不能退出循环,否则表示请求告一段落,可以做一些其他的事情。另外一个while循环,我们检查$active参数,如果该参数为真,则说明还有请求没有完成,需要继续;然后我们执行curl_multi_select函数,这个函数是阻塞的,有连接活动的时候,它才返回;这个时候,我们再使用curl_multi_exec函数去处理连接。
如果不使用curl_multi_select,仅仅使用curl_multi_exec循环知道$active == false ,则脚本一直在阻塞执行,cpu占用一直100%。
2) 通过测试,很容易得到结论,curl_multi的请求时间,略大于最慢的请求的执行时间。测试很简单,可以自己写一个php页面,如下即可,curl_mulit中使用不同的参数t构造多个不同的url即可:
<?php
$time = $_GET['t'];
if($time > 0){
sleep($time);
}
var_dump($time);
3)curl_multi是有缺陷的,一个典型的场景是BigPipe,这种Web优化机制需要php脚本同时向后台服务器发起多个请求,每个请求完成则立刻拼装成一个html片断推到前端服务器,通过这种方式实现php向后端服务器请求数据和php向浏览器推送数据的并发,提高效率。curl_mulit机制与此背道而驰,它是在所有请求都完成后才能使用curl_multi_getcontent获取结果,所以没有办法和BigPipe很好的配合。如果做一些改进,在请求过程中,检查哪些请求已经完成了,则可以与BigPipe配合起来。
下面的代码是测试代码,尝试在curl_multi_exec的返回码为CURLM_OK的时候获取某一个请求的返回值,测试结果是成功的;不过因为这不是官方推荐的做法,可能存在风险,如果要使用的话,请务必最好测试。
$active = null;
do {
$mrc = curl_multi_exec($mh,$active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
while ($active and $mrc == CURLM_OK) {
if (curl_multi_select($mh) != -1) {
do {
$mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
}
//这时候尝试使用curl_multi_getcontent去获取请求的返回结果。一个没有完成的请求返回的内容是null,
//而一个完成的请求,如果它有输出,则返回结果是字符串,可以根据这种区别来判断哪些请求已经完成。
foreach ($connomains as $i => $url) {
if($url === null){
continue;
}
$res[$i]=curl_multi_getcontent($conn[$i]);
if($res[$i] !== false){
var_dump("$i = ".$res[$i]);
$connomains[$i] = null;
}
}
}
参考文章:
cURL API文档 http://curl.haxx.se/libcurl/c/curl_multi_init.html
PHP文档中的范例 http://www.php.net/manual/zh/function.curl-multi-exec.php 该范例示例了一个完整的请求过程,不过没有说明。
php中curl的多线程http://xiemingqiang101.blog.163.com/blog/static/586736602008112151559777/ 该文章分析了一下范例,很有帮助。
BigPipe学习研究 http://www.cnblogs.com/sunvince/archive/2011/04/25/2037608.html
淘宝的BigPipe应用实践
相关文章:
PHP中CURL_MULTI的使用方法简单示例(二) 该文章封装curl_multi相关操作,实现了一个CurlMulti类,简化了使用过程。
关键字:php ,curl, curl_multi, curl批处理, BigPipe, curl 并发请求
1)php文档中,curl_multi这一块只有几个函数的形式化说明,和几个没有任何文档的例子。要想细致的了解其用法,就需要查一些curl库的资料,或者看一下其他人的使用心得。最近整理了一下,记在这里,防止以后遗忘。
curl_multi的基本流程如下:
<?php
//curl_multi的初始化过程,需要把curl加入到curl_multi中作为handle
$connomains = array(
"http://www.cnn.com/",
"http://www.canada.com/",
"http://www.yahoo.com/",
"http://www.baidu.com/"
);
$mh = curl_multi_init();
foreach ($connomains as $i => $url) {
$conn[$i]=curl_init($url);
curl_setopt($conn[$i],CURLOPT_RETURNTRANSFER,1);
curl_multi_add_handle ($mh,$conn[$i]);
}
//下面这11行是实际的请求过程,curl_multi_select是为了避免curl_multi_exec死循环占据了所有的cpu资源。
$active = null;
do {
$mrc = curl_multi_exec($mh,$active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
while ($active and $mrc == CURLM_OK) {
if (curl_multi_select($mh) != -1) {
do {
$mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
}
}
//下面是curl的清理过程
foreach ($connomains as $i => $url) {
//获取curl获取到的内容
$res[$i]=curl_multi_getcontent($conn[$i]);
curl_close($conn[$i]);
curl_multi_remove_handle($mh, $conn[$i]);
}
curl_multi_close($mh);
print_r($res);
curl_multi执行过程中,包含了两个主要的循环。一个do-while循环不停的调用curl_multi_exec函数,这个函数是不阻塞的,它执行后返回状态码,如果状态码是CURLM_CALL_MULTI_PERFORM,说明还有工作需要立刻执行,不能退出循环,否则表示请求告一段落,可以做一些其他的事情。另外一个while循环,我们检查$active参数,如果该参数为真,则说明还有请求没有完成,需要继续;然后我们执行curl_multi_select函数,这个函数是阻塞的,有连接活动的时候,它才返回;这个时候,我们再使用curl_multi_exec函数去处理连接。
如果不使用curl_multi_select,仅仅使用curl_multi_exec循环知道$active == false ,则脚本一直在阻塞执行,cpu占用一直100%。
2) 通过测试,很容易得到结论,curl_multi的请求时间,略大于最慢的请求的执行时间。测试很简单,可以自己写一个php页面,如下即可,curl_mulit中使用不同的参数t构造多个不同的url即可:
<?php
$time = $_GET['t'];
if($time > 0){
sleep($time);
}
var_dump($time);
3)curl_multi是有缺陷的,一个典型的场景是BigPipe,这种Web优化机制需要php脚本同时向后台服务器发起多个请求,每个请求完成则立刻拼装成一个html片断推到前端服务器,通过这种方式实现php向后端服务器请求数据和php向浏览器推送数据的并发,提高效率。curl_mulit机制与此背道而驰,它是在所有请求都完成后才能使用curl_multi_getcontent获取结果,所以没有办法和BigPipe很好的配合。如果做一些改进,在请求过程中,检查哪些请求已经完成了,则可以与BigPipe配合起来。
下面的代码是测试代码,尝试在curl_multi_exec的返回码为CURLM_OK的时候获取某一个请求的返回值,测试结果是成功的;不过因为这不是官方推荐的做法,可能存在风险,如果要使用的话,请务必最好测试。
$active = null;
do {
$mrc = curl_multi_exec($mh,$active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
while ($active and $mrc == CURLM_OK) {
if (curl_multi_select($mh) != -1) {
do {
$mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
}
//这时候尝试使用curl_multi_getcontent去获取请求的返回结果。一个没有完成的请求返回的内容是null,
//而一个完成的请求,如果它有输出,则返回结果是字符串,可以根据这种区别来判断哪些请求已经完成。
foreach ($connomains as $i => $url) {
if($url === null){
continue;
}
$res[$i]=curl_multi_getcontent($conn[$i]);
if($res[$i] !== false){
var_dump("$i = ".$res[$i]);
$connomains[$i] = null;
}
}
}
参考文章:
cURL API文档 http://curl.haxx.se/libcurl/c/curl_multi_init.html
PHP文档中的范例 http://www.php.net/manual/zh/function.curl-multi-exec.php 该范例示例了一个完整的请求过程,不过没有说明。
php中curl的多线程http://xiemingqiang101.blog.163.com/blog/static/586736602008112151559777/ 该文章分析了一下范例,很有帮助。
BigPipe学习研究 http://www.cnblogs.com/sunvince/archive/2011/04/25/2037608.html
淘宝的BigPipe应用实践
相关文章:
PHP中CURL_MULTI的使用方法简单示例(二) 该文章封装curl_multi相关操作,实现了一个CurlMulti类,简化了使用过程。
相关文章推荐
- PHP使用curl_multi实现并发请求的方法示例
- php使用curl简单抓取远程url的方法
- PHP中使用curl伪造IP的简单方法
- php使用curl伪造来源ip和refer的方法示例
- PHP使用curl_multi_select解决curl_multi网页假死问题的方法
- php使用curl简单抓取远程url的方法
- php使用curl简单抓取远程url的方法
- PHP中使用curl伪造IP的简单方法
- PHP 使用 curl_* 系列函数和 curl_multi_* 系列函数进行多接口调用时的性能对比
- PHP使用PDO调用mssql存储过程的方法示例
- PHP使用CURL实现对带有验证码的网站进行模拟登录的方法
- PHP 使用memcached简单示例分享
- php定义数组和使用示例(php数组的定义方法)
- 用Php扩展实现的简单框架 - 6 - 使用示例
- 使用PHP输出CSV和EXCEL文件的简单方法
- php定义数组和使用示例(php数组的定义方法)
- PHP使用CURL实现对带有验证码的网站进行模拟登录的方法
- php之Smarty模板使用方法示例详解