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("\r\n\r\n", $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);

可以看出,異步的效果還是很明顯的


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM