PHP下curl_multi执行一直停不下来

莫名其妙,CPU负责特别高。而且下面代码执行的Job执行了好几天,硬是没有结束。为什么程序会结束不了?

整个代码里就只有这个循环,所以应该是下面的do-while没有结束的问题。但为什么会结束不了呢?我怀疑是running 始终大于0。会有这种情况吗?

<?php
public function run()
{
    $mh = curl_multi_init();
    foreach ($this->_serverList as $key => $hostname) {

        $url = "http://{$hostname}:8360/MonitorInterfaceJob.php?interval=" . $this->_timeInterval;
        $ch[$key] = curl_init($url);
        curl_setopt($ch[$key], CURLOPT_HEADER, 0);
        curl_setopt($ch[$key], CURLOPT_RETURNTRANSFER, true);

        curl_multi_add_handle($mh, $ch[$key]);
    }
    
    //这里有个循环
    do {
        curl_multi_exec($mh, $running);
    } while ($running > 0);

    foreach ($this->_serverList as $key => $hostname) {
        curl_multi_remove_handle($mh, $ch[$key]);
    }

    curl_multi_close($mh);
}

对比官方参考的代码:

$active = null;

// 执行批处理句柄
do {
    $mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);

while ($active && $mrc == CURLM_OK) {
    if (curl_multi_select($mh) != -1) {
        do {
            $mrc = curl_multi_exec($mh, $active);
        } while ($mrc == CURLM_CALL_MULTI_PERFORM);
    }
}

做了如下推断:

  1. 对单个curl没有设置请求的过期时间。但是php都默认设置了超时时间。所以这个是不应该的。
  2. 对比官方推荐的代码,其实running 都是作为程序判断逻辑的。只是官方推荐的代码,严格按照libcurl来执行。
  3. curl_multi通过select()还是poll()的方式做调用,我先不做区分。但我理解这种方式,等价于一个长轮询,所以CPU消耗的比较客观。

请大家帮忙分析分析

慕莱坞森
浏览 1161回答 2
2回答

大话西游666

看curl代码中的curl_multi_perform函数来说,如果是CURLM_BAD_HANDLE,或者CURLM_RECURSIVE_API_CALL的情况下,是没有机会去更新*running_handles = multi->num_alive;这时候如果只判断了running,则会陷入死循环。官方给的代码,只会在返回值为CURLM_OK或者CURLM_CALL_MULTI_PERFORM的情况下循环。 那我来大胆蒙一下:如果通过curl_multi_init()创建mh后 && 请求结束前,由于网络等原因导致mh失效、连接断开等,会导致上述死循环。

慕田峪4524236

额,既然怀疑,就把$running打到log里去看看呗,不然你发上来也看不出$running是啥啊。。。
打开App,查看更多内容
随时随地看视频慕课网APP