zoukankan      html  css  js  c++  java
  • PHP CURL 异步测试

    需求, 请求第三方接口获取数据, 单个接口0.1秒, 如果有10万个接口, 那么岂不是得1万秒才能请求完, 所以使用PHP异步测试一下, 其他的方法还有:

    1.使用队列, SupserVior 开多个进程

    2.使用Guzzle(异步)

    3.使用Swoole协程

    4.直接使用多进程等

    不过最好的方法应该还是使用异步, 不过可能存在两个缺点

    1.异步不是很方便后续的逻辑处理, 应为它是一起请求的

    2.并发请求会导致第三方接口可能处理不了, 导致503错误,或者是cpu满载(请求淘宝IP查询的接口出现过)

    这里做个测试,使用淘宝的一个商品查询接口做请求

    一.不使用异步

    <?php
    
    /**
     * 1个请求      耗时 0.19000s,  平均每个耗时:0.19000s 
     * 10个请求     耗时 1.60000s,  平均每个耗时:0.16000s 
     * 100个请求    耗时 14.92400s, 平均每个耗时:0.14924s 
     * 1000个请求   超时
     * 
     */
    
    
        set_time_limit(0);
        $time = microtime(true);
        echo '<pre>开始时间' . date('Y-m-d H:i:s', time()) . '<br>';
    
        $data = $res =[];
        $count  = 1000;
    
        for ($i=0; $i <$count ; $i++) { 
            $url = 'https://suggest.taobao.com/sug?code=utf-8&q=%E5%8D%AB%E8%A1%A3&callback=cb';
            $res[] = curl_request($url);
        }
    
    
        function curl_request($url, $post='', $cookie='', $returnCookie=0)
        {
            $curl = curl_init();
            curl_setopt($curl, CURLOPT_URL, $url);
            curl_setopt($curl, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)');
            curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);
            curl_setopt($curl, CURLOPT_AUTOREFERER, 1);
            curl_setopt($curl, CURLOPT_REFERER, "http://XXX");
    
            //关闭SSL验证
            curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
            curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
    
            if($post) {
                curl_setopt($curl, CURLOPT_POST, 1);
                curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($post));
            } else {
                //curl_setopt($curl, CURLOPT_POST, 1); //使用后大概快了20%, 但是这个是post请求的
            }
    
            if($cookie) {
                curl_setopt($curl, CURLOPT_COOKIE, $cookie);
            }
            curl_setopt($curl, CURLOPT_HEADER, $returnCookie);
            curl_setopt($curl, CURLOPT_TIMEOUT, 10);
            curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
            $data = curl_exec($curl);
            if (curl_errno($curl)) {
                return curl_error($curl);
            }
            curl_close($curl);
            if($returnCookie){
                list($header, $body) = explode("
    
    ", $data, 2);
                preg_match_all("/Set-Cookie:([^;]*);/", $header, $matches);
                $info['cookie']  = substr($matches[1][0], 1);
                $info['content'] = $body;
                return $info;
            }else{
                return $data;
            }
        }
    
        $cost = microtime(true) - $time;
        echo "结束时间" .  date('Y-m-d H:i:s', time()) . ', 耗时 '. sprintf('%.5f', $cost) . 's, 平均每个耗时:' . sprintf('%.5f', $cost / $count) . 's <br>';
        
    
        var_dump($res);

    二.使用异步请求

    <?php
    
    /**
     * 1个请求      耗时 0.16300s   平均每个耗时:0.16300s 
     * 10个请求     耗时 0.33500s   平均每个耗时:0.03350s 
     * 100个请求    耗时 1.62600s,  平均每个耗时:0.01626s 
     * 1000个请求   耗时 22.27700s, 平均每个耗时:0.02228s 
     * 
     */
    
    $time = microtime(true);
    echo '<pre>开始时间' . date('Y-m-d H:i:s', time()) . '<br>';
    
    set_time_limit(0);
    
    $data = [];
    $count = 1000;
    
    for ($i=0; $i <$count ; $i++) { 
        $url = 'https://suggest.taobao.com/sug?code=utf-8&q=%E5%8D%AB%E8%A1%A3&callback=cb';
        $data[]['url'] = $url;
    }
    
    
    function getMultiCurlResult($data = [], $timeout = 120)
    {
        $request = [];
        $requestResource = curl_multi_init();
        foreach ($data as $k => $v) {
            $option = [
                CURLOPT_TIMEOUT => $timeout,//请求超时时间,防止死循环
                CURLOPT_RETURNTRANSFER => true,//获取的信息以文件流的形式返回,而不是直接输出。
            ];
            if (!isset($v['url']) || !$v['url']) return null;
            $option[CURLOPT_URL] = trim($v['url']);
            if (stripos($v['url'], 'https') === 0) $option[CURLOPT_SSL_VERIFYPEER] = false;
    
            if (isset($v['data'])) {//如果设置了请求参数,则是POST请求
                $option[CURLOPT_POST] = true;
                $option[CURLOPT_POSTFIELDS] = http_build_query($v['data']);
            }
    
            //启动一个curl会话
            $request[$k] = curl_init();
            //设置请求选项
            curl_setopt_array($request[$k], $option);
            //添加请求句柄
            curl_multi_add_handle($requestResource, $request[$k]);
        }
    
        $running = null;
        $result = [];
        do {//执行批处理句柄
            //CURLOPT_RETURNTRANSFER如果为0,这里会直接输出获取到的内容.如果为1,后面可以用curl_multi_getcontent获取内容.
            curl_multi_exec($requestResource, $running);
            //阻塞直到cURL批处理连接中有活动连接,不加这个会导致CPU负载超过90%.
            curl_multi_select($requestResource);
        } while ($running > 0);
    
        foreach ($request as $k => $v) {
            $result[$k] = curl_multi_getcontent($v);
            curl_multi_remove_handle($requestResource, $v);
        }
        curl_multi_close($requestResource);
    
        return $result;
    }
    
    $res = getMultiCurlResult($data);
    
    $cost = microtime(true) - $time;
    echo "结束时间" .  date('Y-m-d H:i:s', time()) . ', 耗时 '. sprintf('%.5f', $cost) . 's, 平均每个耗时:' . sprintf('%.5f', $cost / $count) . 's <br>';
    
    var_dump($res);

    可以看出,异步的效果还是很明显的

  • 相关阅读:
    ORACLE SEQUENCE 介绍
    cocos2d 游戏开发:Cocos2d v3 &quot;hello world&quot;+显示飞船
    无线网络覆盖
    解决xShell4某些情况下按删除键会输出^H的问题
    Android开发经验之—intent传递大数据
    简单的REST的框架实现
    ListView 使用方法(Asp.Net)
    POJ2528 Mayor&#39;s posters 【线段树】+【成段更新】+【离散化】
    C#反射Assembly 具体说明
    HDU 4432 Sum of divisors (进制模拟)
  • 原文地址:https://www.cnblogs.com/Skrillex/p/11574619.html
Copyright © 2011-2022 走看看