【问题标题】:Intermittently echo out data with long-running PHP script使用长时间运行的 PHP 脚本间歇性地回显数据
【发布时间】:2013-12-01 19:39:00
【问题描述】:

我有一个发出一堆 cURL 请求的 PHP 脚本。在每个 cURL 请求之后,我想回显一些数据,但目前,只有在每 5-10 个 cURL 请求后才会回显数据。

我尝试过使用ob_flushflush,但似乎没有什么不同。以下是我的脚本的基本流程:

<?php

  header('Content-Type: text/html; charset=UTF-8');

  set_time_limit(0);

  ob_start();

  $arr = array(); // Lots of strings in this array

  foreach ($arr as $elem) {

    // Use $elem to make cURL request and return HTML.
    // Run regexes on returned HTML.

    echo '<pre>';

    print_r($matches[1]);

    print_r($matches[2]);

    echo '</pre>';

    ob_flush();

    flush();

  }

我能做些什么来强制脚本在每次迭代 foreach 循环后输出 echoed/print_r'ed 数据?

非常感谢。

【问题讨论】:

  • 是否启用了 mod deflate ?
  • 它被禁用了,但我只是取消了httpd.conf文件中LoadModule deflate_module modules/mod_deflate.so的注释并重新启动了Apache服务器,但它似乎没有任何区别。
  • 我应该提一下,如果您从命令行运行这样的脚本,无论回显的数据量如何,它都会在您询问时输出您想要的所有数据。此外,您不需要使用 ob_ 函数。

标签: php curl flush output-buffering long-running-processes


【解决方案1】:

你需要在循环内移动ob_start(),如下:

<?php

  header('Content-Type: text/html; charset=UTF-8');

  set_time_limit(0);

  $arr = array(); // Lots of strings in this array

  foreach ($arr as $elem) {

    ob_start();

    // Use $elem to make cURL request and return HTML.
    // Run regexes on returned HTML.

    echo '<pre>';

    print_r($matches[1]);

    print_r($matches[2]);

    echo '</pre>';

    ob_end_flush();

    flush();

  }

将输出缓冲区 (ob_*) 想象为堆栈上的推送和弹出功能。您可以通过将缓冲区压入堆栈 (ob_start()) 来指定要开始记录的位置,然后在要输出时,将缓冲区从堆栈中弹出并处理结果(ob_flush()ob_get_*()、 ETC)。每个ob_start()必须有一个匹配的缓冲区结束函数。

您还需要使用ob_end_flush() 而不是ob_flush(),因为我认为您不想在每次运行后保留缓冲区。

【讨论】:

  • 我试过这个,但它没有达到我想要的效果。事实上,当我这样做时,脚本会等待所有 cURL 请求完成,然后再一次输出所有内容。
  • 我添加了一条关于 ob_flush()ob_end_flush() 的注释,这也没用?
  • 我只是尝试了ob_end_flush,它确实略有不同,但数据仍然仅每 10 个 cURL 请求左右输出一次。不过有几件事我想知道:1)每个 cURL 请求我只输出大约 500 个字符的文本。少量数据是否可能导致 PHP 合并请求? 2) 我尝试按照 user1281385 的建议启用 mod_deflate,但这似乎没有什么不同。我需要担心吗?
  • mod_deflate 意味着无论出于何种目的和目的,ob_* 函数都将被忽略,因为服务器端必须在发送之前收集整个输出并对其进行压缩。但是如果你得到增量结果,它可能不是 mod_default。你能在 ob_start() 之前、curl 东西之前和 ob_end_flush() 之前放置一个 echo microtime(); 吗?
  • 其实,废了微时间。也许我错了,你需要us2.php.net/manual/en/function.flush.php。可能值得添加一些行尾。
【解决方案2】:

尝试在开始时使用它:

apache_setenv('no-gzip', 1);
ini_set('output_buffering', 0);
ini_set('zlib.output_compression', 0);
ini_set('implicit_flush', 1);

然后做你已经做过的事情。

【讨论】:

  • 感谢您的回答。不幸的是,这根本没有加速任何事情。我仍然只能每 7-8 个请求获得输出。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-12
  • 2019-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多