Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/270.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/apache/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP多重卷曲性能比顺序文件\u获取\u内容差_Php_Apache_Curl_Curl Multi - Fatal编程技术网

PHP多重卷曲性能比顺序文件\u获取\u内容差

PHP多重卷曲性能比顺序文件\u获取\u内容差,php,apache,curl,curl-multi,Php,Apache,Curl,Curl Multi,我正在编写一个接口,在这个接口中,我必须启动4个http请求来获取一些信息 我通过两种方式实现了接口: 使用顺序文件获取内容 使用多重卷曲 我已经用jmeter对这两个版本进行了基准测试。结果表明,当jmeter中只有1个线程发出请求时,multi-curl比sequential file_-get_-contents好得多,但当有100个线程发出请求时,multi-curl比sequential file_-get_-contents差得多 问题是:哪一个可能会带来multi-curl的糟糕性

我正在编写一个接口,在这个接口中,我必须启动4个http请求来获取一些信息

我通过两种方式实现了接口:

  • 使用顺序文件获取内容
  • 使用多重卷曲
  • 我已经用jmeter对这两个版本进行了基准测试。结果表明,当jmeter中只有1个线程发出请求时,multi-curl比sequential file_-get_-contents好得多,但当有100个线程发出请求时,multi-curl比sequential file_-get_-contents差得多

    问题是:哪一个可能会带来multi-curl的糟糕性能

    我的multi-curl代码如下所示:

    $curl_handle_arr = array ();
    $master = curl_multi_init();
    foreach ( $call_url_arr as $key => $url )
    {
        $curl_handle = curl_init( $url );
        $curl_handle_arr [$key] = $curl_handle;
        curl_setopt( $curl_handle , CURLOPT_RETURNTRANSFER , true );
        curl_setopt( $curl_handle , CURLOPT_POST , true );
        curl_setopt( $curl_handle , CURLOPT_POSTFIELDS , http_build_query( $params_arr [$key] ) );
        curl_multi_add_handle( $master , $curl_handle );
    }
    $running = null;
    $mrc = null;
    do
    {
        $mrc = curl_multi_exec( $master , $running );
    }
    while ( $mrc == CURLM_CALL_MULTI_PERFORM );
    while ( $running && $mrc == CURLM_OK )
    {
        if (curl_multi_select( $master ) != - 1)
        {
            do
            {
                $mrc = curl_multi_exec( $master , $running );
            }
            while ( $mrc == CURLM_CALL_MULTI_PERFORM );
        }
    }
    foreach ( $call_url_arr as $key => $url )
    {
        $curl_handle = $curl_handle_arr [$key];
        if (curl_error( $curl_handle ) == '')
        {
            $result_str_arr [$key] = curl_multi_getcontent( $curl_handle );
        }
        curl_multi_remove_handle( $master , $curl_handle );
    }
    curl_multi_close( $master );
    
    1.简单优化
    • 如果
      curl\u multi\u select
      失败,您应该睡眠约2500微秒。
      实际上,每次执行都会失败。
      如果不睡眠,您的CPU资源将被大量
      占用,而(true){}
      循环将被占用
    • 如果在部分请求(并非全部)完成后不执行任何操作,
      您应该让最大超时秒数变大
    • 您的代码是为旧libcurl编写的。从libcurl版本7.2开始,
      状态
      CURLM\u CALL\u MULTI\u PERFORM
      不再出现
    那么,下面的代码

    $running = null;
    $mrc = null;
    do
    {
        $mrc = curl_multi_exec( $master , $running );
    }
    while ( $mrc == CURLM_CALL_MULTI_PERFORM );
    while ( $running && $mrc == CURLM_OK )
    {
        if (curl_multi_select( $master ) != - 1)
        {
            do
            {
                $mrc = curl_multi_exec( $master , $running );
            }
            while ( $mrc == CURLM_CALL_MULTI_PERFORM );
        }
    }
    
    应该是

    curl_multi_exec($master, $running);
    do
    {
        if (curl_multi_select($master, 99) === -1)
        {
            usleep(2500);
            continue;
        }
        curl_multi_exec($master, $running);
    } while ($running);
    
    注 只有当您想执行以下操作时,
    curl\u multi\u select
    的超时值才应调整

    curl_multi_exec($master, $running);
    do
    {
        if (curl_multi_select($master, $TIMEOUT) === -1)
        {
            usleep(2500);
            continue;
        }
        curl_multi_exec($master, $running);
        while ($info = curl_multi_info_read($master))
        {
            /* Do something with $info */
        }
    } while ($running);
    
    否则,该值应非常大。
    (但是,
    PHP\u INT\u MAX
    太大;libcurl将其视为无效值。)

    2.一个PHP进程中的简单实验 我使用我的并行cURL executor库进行了测试:

    (为准备的
    不合适,应该由
    进行,
    ,对不起,我的英语很差)


    100个线程仅用于4个请求。。。您能给我看一下您的基准测试代码吗?[PR]:异步cURL执行器仅基于资源和生成器。@mpyw,很抱歉我的英语不好。我的意思是:我编写了一个接口,在接口中必须发出4个http请求来获取一些数据,然后接口处理这些数据。我使用jmeter对这两个版本进行了基准测试。当我在jmeter中将线程数设置为100时,multi-curl版本的性能相当差。非常感谢!稍后我会尝试,如果使用curl_setopt函数将4个http请求的超时值分别设置为1s、2s、3s、4s,那么curl\u multi\u select超时的正确值是多少?我已经尝试了您的代码,但结果与以前一样。我还以另一种方式进行了测试。似乎curl multi在高并发情况下是不合适的。我将尝试其他解决方案,并随时通知您。再次感谢您的帮助!
    <?php 
    
    require 'vendor/autoload.php';
    
    use mpyw\Co\Co;
    
    function four_sequencial_requests_for_one_hundread_people()
    {
        for ($i = 0; $i < 100; ++$i) {
            $tasks[] = function () use ($i) {
                $ch = curl_init();
                curl_setopt_array($ch, [
                    CURLOPT_URL => 'example.com',
                    CURLOPT_FORBID_REUSE => true,
                    CURLOPT_RETURNTRANSFER => true,
                ]);
                for ($j = 0; $j < 4; ++$j) {
                    yield $ch;
                }
            };
        }
        $start = microtime(true);
        yield $tasks;
        $end = microtime(true);
        printf("Time of %s: %.2f sec\n", __FUNCTION__, $end - $start);
    }
    
    function requests_for_four_hundreds_people()
    {
        for ($i = 0; $i < 400; ++$i) {
            $tasks[] = function () use ($i) {
                $ch = curl_init();
                curl_setopt_array($ch, [
                    CURLOPT_URL => 'example.com',
                    CURLOPT_FORBID_REUSE => true,
                    CURLOPT_RETURNTRANSFER => true,
                ]);
                yield $ch;
            };
        }
        $start = microtime(true);
        yield $tasks;
        $end = microtime(true);
        printf("Time of %s: %.2f sec\n", __FUNCTION__, $end - $start);
    }
    
    Co::wait(four_sequencial_requests_for_one_hundread_people(), [
        'concurrency' => 0, // Zero means unlimited
    ]);
    
    Co::wait(requests_for_four_hundreds_people(), [
        'concurrency' => 0, // Zero means unlimited
    ]);
    
    curl_multi_setopt($master, CURLMOPT_PIPELINING, 1);