PHP中CURL_MULTI的使用方法简单示例

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类,简化了使用过程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值