• PHP多线程 curl_multi_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 "
    ";
    
    //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 "
    ";
    
    ?>

    运行结果:

    * 当$count=10的情况下,耗时分别为:

    3.4119510650635
    0.44486904144287

    curl_multi_init() 比 curl_init() 快了8倍。

    * 当 $count=100的情况下,耗时分别为:

    34.190015077591
    1.9350771903992

    curl_multi_init() 比 curl_init() 快了17倍。

  • 相关阅读:
    kubernetes进阶(一) kubectl工具使用详解
    二进制安装kubernetes(七) 部署知识点总结
    1024程序员节:这就是国内开发者的现状?
    php 伪协议
    浅谈 PHP 与手机 APP 开发(API 接口开发)
    比RBAC更好的权限认证方式(Auth类认证)
    PHP获得毫秒数
    2020年PHP面试题附答案(实战经验)
    分享几套2019年各大公司最新的PHP面试题,几斤几两一试便知
    PHP面试题2019年百度工程师面试题及答案解析
  • 原文地址:https://www.cnblogs.com/rxbook/p/10764080.html
Copyright © 2020-2023  润新知