需求, 請求第三方接口獲取數據, 單個接口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);
可以看出,異步的效果還是很明顯的