PHP中使用curl_multi调用多API反而更慢,求排查问题原因
你的curl_multi比file_get_contents慢的问题出在这几个地方
首先,你写的curl_multi循环一直在空轮询,导致CPU持续满负荷运行,反而拖慢了整体速度。另外还有些小的代码问题,我给你拆解清楚:
核心问题:无等待的空轮询
原代码里的这段循环:
do { curl_multi_exec($master,$running); } while($running > 0);
会不断重复调用curl_multi_exec,哪怕当前没有任何网络数据返回,CPU全程空转,浪费大量资源,自然比串行的file_get_contents还慢。正确的做法是加入curl_multi_select,让进程在没有活动连接时休眠,避免无效消耗:
do { $status = curl_multi_exec($master, $running); if ($running) { // 等待活动连接,释放CPU资源 curl_multi_select($master); } } while ($running && $status == CURLM_OK);
其他问题及优化点
- 漏掉第一个请求的结果:获取内容的循环从
$i=1开始,索引0的请求结果被忽略了,虽然不影响计时,但属于逻辑错误,应该从$i=0开始遍历。 - 缺少curl效率优化配置:可以添加一些选项提升请求速度,比如设置超时、测试场景下禁用SSL证书验证、开启TCP复用等:
curl_setopt($curl_arr[$i], CURLOPT_TIMEOUT, 10); curl_setopt($curl_arr[$i], CURLOPT_SSL_VERIFYPEER, false); curl_setopt($curl_arr[$i], CURLOPT_SSL_VERIFYHOST, false); curl_setopt($curl_arr[$i], CURLOPT_TCP_KEEPALIVE, true);
- 未释放资源:原代码没有关闭curl句柄和multi句柄,长期运行会导致资源泄漏,修正时要补充相关关闭逻辑。
修正后的完整代码
<?php $start = microtime(true); $urls = array("https://www.example1.com/", "https://www.example2.com/", "https://www.example3.com/"); $urls_count = count($urls); $curl_arr = array(); $master = curl_multi_init(); for($i = 0; $i < $urls_count; $i++) { $curl_arr[$i] = curl_init($urls[$i]); curl_setopt($curl_arr[$i], CURLOPT_RETURNTRANSFER, true); // 添加优化配置 curl_setopt($curl_arr[$i], CURLOPT_TIMEOUT, 10); curl_setopt($curl_arr[$i], CURLOPT_SSL_VERIFYPEER, false); curl_setopt($curl_arr[$i], CURLOPT_SSL_VERIFYHOST, false); curl_setopt($curl_arr[$i], CURLOPT_TCP_KEEPALIVE, true); curl_multi_add_handle($master, $curl_arr[$i]); } do { $status = curl_multi_exec($master, $running); if ($running) { curl_multi_select($master); } } while ($running && $status == CURLM_OK); // 遍历所有请求获取结果 $results = []; for($i = 0; $i < $urls_count; $i++) { $results[] = curl_multi_getcontent($curl_arr[$i]); // 释放句柄资源 curl_multi_remove_handle($master, $curl_arr[$i]); curl_close($curl_arr[$i]); } curl_multi_close($master); echo microtime(true) - $start; ?>
这样修改后,curl_multi的并行优势就能正常发挥,速度会明显快于串行的file_get_contents。
内容的提问来源于stack exchange,提问作者Frederik Greve
相关产品推荐
相关产品推荐

