PHP CURL 异步测试
<p>需求, 请求第三方接口获取数据, 单个接口0.1秒, 如果有10万个接口, 那么岂不是得1万秒才能请求完, 所以使用PHP异步测试一下, 其他的方法还有:</p><p>1.使用队列, SupserVior 开多个进程</p>
<p>2.使用Guzzle(异步)</p>
<p>3.使用Swoole协程</p>
<p>4.直接使用多进程等</p>
<p>不过最好的方法应该还是使用异步, 不过可能存在两个缺点</p>
<p>1.异步不是很方便后续的逻辑处理, 应为它是一起请求的</p>
<p>2.并发请求会导致第三方接口可能处理不了, 导致503错误,或者是cpu满载(请求淘宝IP查询的接口出现过)</p>
<p> </p>
<p>这里做个测试,使用淘宝的一个商品查询接口做请求</p>
<p>一.不使用异步</p>
<div class="cnblogs_code">
<pre><?<span style="color: rgba(0, 0, 0, 1)">php
</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
* 1个请求 耗时 0.19000s,平均每个耗时:0.19000s
* 10个请求 耗时 1.60000s,平均每个耗时:0.16000s
* 100个请求 耗时 14.92400s, 平均每个耗时:0.14924s
* 1000个请求 超时
*
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 128, 128, 1)">set_time_limit</span>(0<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(128, 0, 128, 1)">$time</span> = <span style="color: rgba(0, 128, 128, 1)">microtime</span>(<span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> '<pre>开始时间' . <span style="color: rgba(0, 128, 128, 1)">date</span>('Y-m-d H:i:s', <span style="color: rgba(0, 128, 128, 1)">time</span>()) . '<br>'<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(128, 0, 128, 1)">$data</span> = <span style="color: rgba(128, 0, 128, 1)">$res</span> =<span style="color: rgba(0, 0, 0, 1)">[];
</span><span style="color: rgba(128, 0, 128, 1)">$count</span>= 1000<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(128, 0, 128, 1)">$i</span>=0; <span style="color: rgba(128, 0, 128, 1)">$i</span> <<span style="color: rgba(128, 0, 128, 1)">$count</span> ; <span style="color: rgba(128, 0, 128, 1)">$i</span>++<span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(128, 0, 128, 1)">$url</span> = 'https://suggest.taobao.com/sug?code=utf-8&q=%E5%8D%AB%E8%A1%A3&callback=cb'<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(128, 0, 128, 1)">$res</span>[] = curl_request(<span style="color: rgba(128, 0, 128, 1)">$url</span><span style="color: rgba(0, 0, 0, 1)">);
}
</span><span style="color: rgba(0, 0, 255, 1)">function</span> curl_request(<span style="color: rgba(128, 0, 128, 1)">$url</span>, <span style="color: rgba(128, 0, 128, 1)">$post</span>='', <span style="color: rgba(128, 0, 128, 1)">$cookie</span>='', <span style="color: rgba(128, 0, 128, 1)">$returnCookie</span>=0<span style="color: rgba(0, 0, 0, 1)">)
{
</span><span style="color: rgba(128, 0, 128, 1)">$curl</span> =<span style="color: rgba(0, 0, 0, 1)"> curl_init();
curl_setopt(</span><span style="color: rgba(128, 0, 128, 1)">$curl</span>, CURLOPT_URL, <span style="color: rgba(128, 0, 128, 1)">$url</span><span style="color: rgba(0, 0, 0, 1)">);
curl_setopt(</span><span style="color: rgba(128, 0, 128, 1)">$curl</span>, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0)'<span style="color: rgba(0, 0, 0, 1)">);
curl_setopt(</span><span style="color: rgba(128, 0, 128, 1)">$curl</span>, CURLOPT_FOLLOWLOCATION, 1<span style="color: rgba(0, 0, 0, 1)">);
curl_setopt(</span><span style="color: rgba(128, 0, 128, 1)">$curl</span>, CURLOPT_AUTOREFERER, 1<span style="color: rgba(0, 0, 0, 1)">);
curl_setopt(</span><span style="color: rgba(128, 0, 128, 1)">$curl</span>, CURLOPT_REFERER, "http://XXX"<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">关闭SSL验证</span>
curl_setopt(<span style="color: rgba(128, 0, 128, 1)">$curl</span>, CURLOPT_SSL_VERIFYPEER, 0<span style="color: rgba(0, 0, 0, 1)">);
curl_setopt(</span><span style="color: rgba(128, 0, 128, 1)">$curl</span>, CURLOPT_SSL_VERIFYHOST, 0<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">if</span>(<span style="color: rgba(128, 0, 128, 1)">$post</span><span style="color: rgba(0, 0, 0, 1)">) {
curl_setopt(</span><span style="color: rgba(128, 0, 128, 1)">$curl</span>, CURLOPT_POST, 1<span style="color: rgba(0, 0, 0, 1)">);
curl_setopt(</span><span style="color: rgba(128, 0, 128, 1)">$curl</span>, CURLOPT_POSTFIELDS, <span style="color: rgba(0, 128, 128, 1)">http_build_query</span>(<span style="color: rgba(128, 0, 128, 1)">$post</span><span style="color: rgba(0, 0, 0, 1)">));
} </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">curl_setopt($curl, CURLOPT_POST, 1); //使用后大概快了20%, 但是这个是post请求的</span>
<span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 0, 255, 1)">if</span>(<span style="color: rgba(128, 0, 128, 1)">$cookie</span><span style="color: rgba(0, 0, 0, 1)">) {
curl_setopt(</span><span style="color: rgba(128, 0, 128, 1)">$curl</span>, CURLOPT_COOKIE, <span style="color: rgba(128, 0, 128, 1)">$cookie</span><span style="color: rgba(0, 0, 0, 1)">);
}
curl_setopt(</span><span style="color: rgba(128, 0, 128, 1)">$curl</span>, CURLOPT_HEADER, <span style="color: rgba(128, 0, 128, 1)">$returnCookie</span><span style="color: rgba(0, 0, 0, 1)">);
curl_setopt(</span><span style="color: rgba(128, 0, 128, 1)">$curl</span>, CURLOPT_TIMEOUT, 10<span style="color: rgba(0, 0, 0, 1)">);
curl_setopt(</span><span style="color: rgba(128, 0, 128, 1)">$curl</span>, CURLOPT_RETURNTRANSFER, 1<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(128, 0, 128, 1)">$data</span> = curl_exec(<span style="color: rgba(128, 0, 128, 1)">$curl</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (curl_errno(<span style="color: rgba(128, 0, 128, 1)">$curl</span><span style="color: rgba(0, 0, 0, 1)">)) {
</span><span style="color: rgba(0, 0, 255, 1)">return</span> curl_error(<span style="color: rgba(128, 0, 128, 1)">$curl</span><span style="color: rgba(0, 0, 0, 1)">);
}
curl_close(</span><span style="color: rgba(128, 0, 128, 1)">$curl</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">if</span>(<span style="color: rgba(128, 0, 128, 1)">$returnCookie</span><span style="color: rgba(0, 0, 0, 1)">){
</span><span style="color: rgba(0, 0, 255, 1)">list</span>(<span style="color: rgba(128, 0, 128, 1)">$header</span>, <span style="color: rgba(128, 0, 128, 1)">$body</span>) = <span style="color: rgba(0, 128, 128, 1)">explode</span>("\r\n\r\n", <span style="color: rgba(128, 0, 128, 1)">$data</span>, 2<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">preg_match_all</span>("/Set\-Cookie:([^;]*);/", <span style="color: rgba(128, 0, 128, 1)">$header</span>, <span style="color: rgba(128, 0, 128, 1)">$matches</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(128, 0, 128, 1)">$info</span>['cookie']= <span style="color: rgba(0, 128, 128, 1)">substr</span>(<span style="color: rgba(128, 0, 128, 1)">$matches</span>, 1<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(128, 0, 128, 1)">$info</span>['content'] = <span style="color: rgba(128, 0, 128, 1)">$body</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 128, 1)">$info</span><span style="color: rgba(0, 0, 0, 1)">;
}</span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">{
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 128, 1)">$data</span><span style="color: rgba(0, 0, 0, 1)">;
}
}
</span><span style="color: rgba(128, 0, 128, 1)">$cost</span> = <span style="color: rgba(0, 128, 128, 1)">microtime</span>(<span style="color: rgba(0, 0, 255, 1)">true</span>) - <span style="color: rgba(128, 0, 128, 1)">$time</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> "结束时间" .<span style="color: rgba(0, 128, 128, 1)">date</span>('Y-m-d H:i:s', <span style="color: rgba(0, 128, 128, 1)">time</span>()) . ', 耗时 '. <span style="color: rgba(0, 128, 128, 1)">sprintf</span>('%.5f', <span style="color: rgba(128, 0, 128, 1)">$cost</span>) . 's, 平均每个耗时:' . <span style="color: rgba(0, 128, 128, 1)">sprintf</span>('%.5f', <span style="color: rgba(128, 0, 128, 1)">$cost</span> / <span style="color: rgba(128, 0, 128, 1)">$count</span>) . 's <br>'<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">var_dump</span>(<span style="color: rgba(128, 0, 128, 1)">$res</span>);</pre>
</div>
<p> </p>
<p>二.使用异步请求</p>
<div class="cnblogs_code">
<pre><?<span style="color: rgba(0, 0, 0, 1)">php
</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">*
* 1个请求 耗时 0.16300s 平均每个耗时:0.16300s
* 10个请求 耗时 0.33500s 平均每个耗时:0.03350s
* 100个请求 耗时 1.62600s,平均每个耗时:0.01626s
* 1000个请求 耗时 22.27700s, 平均每个耗时:0.02228s
*
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(128, 0, 128, 1)">$time</span> = <span style="color: rgba(0, 128, 128, 1)">microtime</span>(<span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> '<pre>开始时间' . <span style="color: rgba(0, 128, 128, 1)">date</span>('Y-m-d H:i:s', <span style="color: rgba(0, 128, 128, 1)">time</span>()) . '<br>'<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">set_time_limit</span>(0<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(128, 0, 128, 1)">$data</span> =<span style="color: rgba(0, 0, 0, 1)"> [];
</span><span style="color: rgba(128, 0, 128, 1)">$count</span> = 1000<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">for</span> (<span style="color: rgba(128, 0, 128, 1)">$i</span>=0; <span style="color: rgba(128, 0, 128, 1)">$i</span> <<span style="color: rgba(128, 0, 128, 1)">$count</span> ; <span style="color: rgba(128, 0, 128, 1)">$i</span>++<span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(128, 0, 128, 1)">$url</span> = 'https://suggest.taobao.com/sug?code=utf-8&q=%E5%8D%AB%E8%A1%A3&callback=cb'<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(128, 0, 128, 1)">$data</span>[]['url'] = <span style="color: rgba(128, 0, 128, 1)">$url</span><span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(0, 0, 255, 1)">function</span> getMultiCurlResult(<span style="color: rgba(128, 0, 128, 1)">$data</span> = [], <span style="color: rgba(128, 0, 128, 1)">$timeout</span> = 120<span style="color: rgba(0, 0, 0, 1)">)
{
</span><span style="color: rgba(128, 0, 128, 1)">$request</span> =<span style="color: rgba(0, 0, 0, 1)"> [];
</span><span style="color: rgba(128, 0, 128, 1)">$requestResource</span> =<span style="color: rgba(0, 0, 0, 1)"> curl_multi_init();
</span><span style="color: rgba(0, 0, 255, 1)">foreach</span> (<span style="color: rgba(128, 0, 128, 1)">$data</span> <span style="color: rgba(0, 0, 255, 1)">as</span> <span style="color: rgba(128, 0, 128, 1)">$k</span> => <span style="color: rgba(128, 0, 128, 1)">$v</span><span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(128, 0, 128, 1)">$option</span> =<span style="color: rgba(0, 0, 0, 1)"> [
CURLOPT_TIMEOUT </span>=> <span style="color: rgba(128, 0, 128, 1)">$timeout</span>,<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">请求超时时间,防止死循环</span>
CURLOPT_RETURNTRANSFER => <span style="color: rgba(0, 0, 255, 1)">true</span>,<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">获取的信息以文件流的形式返回,而不是直接输出。</span>
<span style="color: rgba(0, 0, 0, 1)"> ];
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 255, 1)">isset</span>(<span style="color: rgba(128, 0, 128, 1)">$v</span>['url']) || !<span style="color: rgba(128, 0, 128, 1)">$v</span>['url']) <span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(128, 0, 128, 1)">$option</span> = <span style="color: rgba(0, 128, 128, 1)">trim</span>(<span style="color: rgba(128, 0, 128, 1)">$v</span>['url'<span style="color: rgba(0, 0, 0, 1)">]);
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 128, 128, 1)">stripos</span>(<span style="color: rgba(128, 0, 128, 1)">$v</span>['url'], 'https') === 0) <span style="color: rgba(128, 0, 128, 1)">$option</span> = <span style="color: rgba(0, 0, 255, 1)">false</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 0, 255, 1)">isset</span>(<span style="color: rgba(128, 0, 128, 1)">$v</span>['data'])) {<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">如果设置了请求参数,则是POST请求</span>
<span style="color: rgba(128, 0, 128, 1)">$option</span> = <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(128, 0, 128, 1)">$option</span> = <span style="color: rgba(0, 128, 128, 1)">http_build_query</span>(<span style="color: rgba(128, 0, 128, 1)">$v</span>['data'<span style="color: rgba(0, 0, 0, 1)">]);
}
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">启动一个curl会话</span>
<span style="color: rgba(128, 0, 128, 1)">$request</span>[<span style="color: rgba(128, 0, 128, 1)">$k</span>] =<span style="color: rgba(0, 0, 0, 1)"> curl_init();
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">设置请求选项</span>
curl_setopt_array(<span style="color: rgba(128, 0, 128, 1)">$request</span>[<span style="color: rgba(128, 0, 128, 1)">$k</span>], <span style="color: rgba(128, 0, 128, 1)">$option</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">添加请求句柄</span>
curl_multi_add_handle(<span style="color: rgba(128, 0, 128, 1)">$requestResource</span>, <span style="color: rgba(128, 0, 128, 1)">$request</span>[<span style="color: rgba(128, 0, 128, 1)">$k</span><span style="color: rgba(0, 0, 0, 1)">]);
}
</span><span style="color: rgba(128, 0, 128, 1)">$running</span> = <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(128, 0, 128, 1)">$result</span> =<span style="color: rgba(0, 0, 0, 1)"> [];
</span><span style="color: rgba(0, 0, 255, 1)">do</span> {<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">执行批处理句柄
//CURLOPT_RETURNTRANSFER如果为0,这里会直接输出获取到的内容.如果为1,后面可以用curl_multi_getcontent获取内容.</span>
curl_multi_exec(<span style="color: rgba(128, 0, 128, 1)">$requestResource</span>, <span style="color: rgba(128, 0, 128, 1)">$running</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">阻塞直到cURL批处理连接中有活动连接,不加这个会导致CPU负载超过90%.</span>
curl_multi_select(<span style="color: rgba(128, 0, 128, 1)">$requestResource</span><span style="color: rgba(0, 0, 0, 1)">);
} </span><span style="color: rgba(0, 0, 255, 1)">while</span> (<span style="color: rgba(128, 0, 128, 1)">$running</span> > 0<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">foreach</span> (<span style="color: rgba(128, 0, 128, 1)">$request</span> <span style="color: rgba(0, 0, 255, 1)">as</span> <span style="color: rgba(128, 0, 128, 1)">$k</span> => <span style="color: rgba(128, 0, 128, 1)">$v</span><span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(128, 0, 128, 1)">$result</span>[<span style="color: rgba(128, 0, 128, 1)">$k</span>] = curl_multi_getcontent(<span style="color: rgba(128, 0, 128, 1)">$v</span><span style="color: rgba(0, 0, 0, 1)">);
curl_multi_remove_handle(</span><span style="color: rgba(128, 0, 128, 1)">$requestResource</span>, <span style="color: rgba(128, 0, 128, 1)">$v</span><span style="color: rgba(0, 0, 0, 1)">);
}
curl_multi_close(</span><span style="color: rgba(128, 0, 128, 1)">$requestResource</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 128, 1)">$result</span><span style="color: rgba(0, 0, 0, 1)">;
}
</span><span style="color: rgba(128, 0, 128, 1)">$res</span> = getMultiCurlResult(<span style="color: rgba(128, 0, 128, 1)">$data</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(128, 0, 128, 1)">$cost</span> = <span style="color: rgba(0, 128, 128, 1)">microtime</span>(<span style="color: rgba(0, 0, 255, 1)">true</span>) - <span style="color: rgba(128, 0, 128, 1)">$time</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">echo</span> "结束时间" .<span style="color: rgba(0, 128, 128, 1)">date</span>('Y-m-d H:i:s', <span style="color: rgba(0, 128, 128, 1)">time</span>()) . ', 耗时 '. <span style="color: rgba(0, 128, 128, 1)">sprintf</span>('%.5f', <span style="color: rgba(128, 0, 128, 1)">$cost</span>) . 's, 平均每个耗时:' . <span style="color: rgba(0, 128, 128, 1)">sprintf</span>('%.5f', <span style="color: rgba(128, 0, 128, 1)">$cost</span> / <span style="color: rgba(128, 0, 128, 1)">$count</span>) . 's <br>'<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">var_dump</span>(<span style="color: rgba(128, 0, 128, 1)">$res</span>);</pre>
</div>
<p>可以看出,异步的效果还是很明显的</p><br><br>
来源:https://www.cnblogs.com/Skrillex/p/11574619.html
頁:
[1]