关闭

curl_multi_init比curl_init快30倍

3041人阅读 评论(0) 收藏 举报
分类:
CleverCode发现curl_multi_init比curl_init发送100个请求,快非常多!具体细节如下。

1 https源码

<?php
/*
 * https.php
 *
 * https请求类 http://blog.csdn.net/CleverCode
 *
 * modification history:
 * --------------------
 * 2016/5/25, by CleverCode, Create
 *
 */
class Https
{/*{{{*/

    /**
     * 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); 
                // 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);

            // 使用代理
            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;
        }

        return null;
    }/*}}}*/

    /**
     * https 发起post多发请求
     * 
     * @param array $nodes url和参数信息。$nodes = array
     *                                              (
     *                                                 [0] = > array
     *                                                   (
     *                                                       'url' => 'http://www.baidu.com',
     *                                                       'data' => '{"a":1,"b":2}'
     *                                                   ),
     *                                                 [1] = > array
     *                                                   (
     *                                                       '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();
        }

        return array();
    }/*}}}*/

}/*}}}*/


2  100个请求

2.1 循环调用https::post()一百次。

<?php

require_once "https.php";

function microtimeFloat()                   
{/*{{{*/                                            
    list($usec, $sec) = explode(" ", microtime());  
    return ($usec + $sec);                          
}/*}}}*/                                            

$url = 'https://api.weixin.qq.com/cgi-bin/getcallbackip?access_token=abcdasdfasdfasdfasdfasdfasdfasdfasdfasdf';

$startTime = microtimeFloat();
$count = 100;
for($i=1; $i <= 100;$i++)
{
    $res = Https::post($url);
}
$endTime = microtimeFloat();

echo $endTime - $startTime;
echo "\r\n";

?>

2.2 调用https::postMulti()一次发100个url。

<?php

require_once "https.php";

function microtimeFloat()                   
{/*{{{*/                                            
    list($usec, $sec) = explode(" ", microtime());  
    return ($usec + $sec);                          
}/*}}}*/                                            

$url = 'https://api.weixin.qq.com/cgi-bin/getcallbackip?access_token=abcdasdfasdfasdfasdfasdfasdfasdfasdfasdf';

$nodes = array();
for($i=1; $i <= 100;$i++)
{
    $info = array();
    $info['url'] = $url;
    $nodes[] = $info;
}

$startTime = microtimeFloat();
$res = Https::post($nodes);
$endTime = microtimeFloat();

echo $endTime - $startTime;
echo "\r\n";

?>

3 结果对比

2.1 方式耗时:15.47503900528。

2.2 方式耗时:0.49252104759216。

15.47503900528 /  0.49252104759216 = 30。

2.2 比2.1快30倍!!!

4 结论

   当需要一次发送多个请求的时候,尽量使用curl_multi_init方式。


2
0
查看评论

利用curl_multi_init并行多线程处理网络数据

利用curl_multi_init并行处理网络数据
  • lg_lin
  • lg_lin
  • 2015-08-14 20:07
  • 1505

php中curl_multi的应用

相信许多人对php手册中语焉不详的curl_multi一族的函数头疼不已,它们文档少,给的例子 更是简单的让你无从借鉴,我也曾经找了许多网页,都没见一个完整的应用例子。curl_multi_add_handle curl_multi_close curl_multi_exec curl_m...
  • oyd
  • oyd
  • 2007-10-11 18:21
  • 12921

php curl_multi批量发送http请求

引子:在Android4.0开发中,发送Http请求已经不允许在主进程中执行了,必须在线程中执行。原因在于Http接口响应时间有可能阻塞主进程事件监听(对于.Net开发,其实也是如此)。但是,由于PHP并没有多线程的概念,那么,如何高效率在PHP中执行多次http请求呢?答案是使用curl_mult...
  • loophome
  • loophome
  • 2015-10-03 16:50
  • 2468

简评file_get_contents与curl 效率及稳定性

做过好多抓取别家网站内容的产品,习惯了使用方便快捷的file_get_contents函数,但是总是会遇到获取失败的问题,尽管按照手册中的例子设置了超时,可多数时候不会奏效: $config['context'] = stream_context_create(array(‘htt...
  • u011553255
  • u011553255
  • 2013-11-13 14:28
  • 697

curl_init()和curl_multi_init()多线程的速度比较

php中curl_init()的作用很大,尤其是在抓取网页内容或文件信息的时候,例如之前文章curl获得header检测GZip压缩的源代码就介绍到curl_init()的强大。 curl_init()处理事物是单线程模式,如果需要对事务处理走多线程模式,那么php里提供了一个函数curl_m...
  • will5451
  • will5451
  • 2017-07-28 17:56
  • 225

curl_multi实现准多线程采集

curl_multi在其内部实现了多线程发送请求,但在php代码层面仍然是单线程阻塞的。
  • Allen_Tsang
  • Allen_Tsang
  • 2016-09-03 21:13
  • 1262

curl_multi_init()多线程

<?php echo date("Y-m-d H:m:s",time()); echo " "; echo floor(microtime()*1000); echo ""; $mtime = explode(" "...
  • q601115211
  • q601115211
  • 2014-10-25 14:50
  • 2733

PHP使用curl_multi并发请求

class CurlMultiUtil { /** * 根据url,postData获取curl请求对象,这个比较简单,可以看官方文档 */ private static function getCurlObject($url,$postData=array(),$h...
  • u013474436
  • u013474436
  • 2016-10-28 15:07
  • 17615

php中curl同时发送多个请求curl_multi函数集的用法

一、引言这段时间比较忙,已经很久没有写博客了。今天我就来聊聊我关于curl_multi_*函数集的使用心得,关于http请求的问题。当我们用户php发起一个http请求的时候。我们会首先想到用什么?没错,我们会创建curl来请求。当我们在一次执行中需要发起多个http请求呢。这简单,对每一个URL发...
  • xueling022
  • xueling022
  • 2016-07-14 11:49
  • 5980

ELK+Filebeat 集中式日志解决方案详解

Google+用电子邮件发送本页面 ELK Stack 简介 ELK 不是一款软件,而是 Elasticsearch、Logstash 和 Kibana 三种软件产品的首字母缩写。这三者都是开源软件,通常配合使用,而且又先后归于 Elastic.co 公司...
  • zoubf
  • zoubf
  • 2017-02-16 10:09
  • 3990
    个人资料
    • 访问:612157次
    • 积分:7186
    • 等级:
    • 排名:第3747名
    • 原创:169篇
    • 转载:6篇
    • 译文:0篇
    • 评论:136条
    推荐微信公众号:PHP专家

             PHP专家(phpexpert)。我们一起成为PHP专家!


    博客专栏
    最新评论