【问题标题】:Don't buffer response for event stream不要缓冲事件流的响应
【发布时间】:2021-08-16 04:02:41
【问题描述】:

我在带有 PHP/7.4.19 的 nginx/1.14.1 服务器上使用 CodeIgniter 3 PHP 框架。

我正在尝试设置事件流。控制器方法如下所示:

public function foo()
{           
    
    // Try everything I can to disable output buffering
    ini_set('output_buffering', 'Off');
    ini_set('implicit_flush', 'On');
    ini_set('zlib.output_compression', 'Off');
    
    header('X-Accel-Buffering: no');
    header("X-Robots-Tag: noindex");
    header('Cache-Control: no-store, no-cache');
    header('Content-Type: text/event-stream');
    header('Content-Encoding: none');
    
    $i = 0;
                   
    // Loop 10 times
    while ($i < 10)
    {

        // Codeigniter built-in function to generate a random alphanumeric string of n characters
        $random_string = random_string('alnum', 10);
        
        $array = array(
            'foo' => $random_string               
        );
        
        // Put together an event
        $output = "event: ping\n";
        $output .= "id: $random_string\n";
        $output .= "data: ";
        $output .= json_encode($array);
        $output .= "\n\n";         
        
        echo $output;
        
        $i++;
        
        ob_end_flush();
        flush();
        
        // Break the loop if the client closed the page
          
        if (connection_aborted())
        {
            break;
        }
        
        sleep(1);
    }    

预期的行为是每个事件一次出现一个,每秒一个。

但是,我似乎无法禁用输出缓冲。在全部 10 个事件完全加载之前,完整的 10 秒过去了。

如果我生成一个大的随机字符串,例如random_string('alnum', 500);,那么页面会以大约 4K 的字符块加载。换句话说,页面大约每 4K 个字符刷新一次缓冲区,并且在页面之前大约需要 3 个这样的块(每个块之间等待 2-3 秒,以适应 while 循环的 2-3 次迭代)完成加载。

我正在使用 Cloudflare,但我有一个页面规则来绕过相关页面上的缓存。这是首页规则。

在 Cloudflare 中禁用了响应缓冲。默认情况下,Cloudflare 在收到数据包时将其发送到客户端。企业帐户(我们不是)可以选择启用响应缓冲。

已启用 Cloudflare Brotli 压缩。暂时禁用它并不能解决问题。

显然,当从命令行运行 php 脚本时,它会按预期工作。

【问题讨论】:

  • 一个疯狂的猜测 - 如果你在 ob_end_flush() 之前调用 flush() 会发生什么?
  • @IvanShatsky 没有变化。
  • 也许 Cloudflare 真的是原因?我回答了similar question 一次,首先在沙箱中尝试了解决方案,一切都按预期工作。抱歉,我没有任何 Cloudflare 帐户,无法为您提供更多帮助。

标签: php codeigniter nginx cloudflare event-stream


【解决方案1】:

我想知道这是否是 Nginx 问题?在 Nginx 后面运行服务器发送事件时,我遇到了类似的问题。解决方法是在响应中添加一个值为“no”的“X-Accel-Buffering”标头。

【讨论】:

    【解决方案2】:

    我可以通过在回显输出之前添加行 $output .= str_pad('', 4096) . "\n\n"; 在 Chrome 中实现所需的结果。

    然而,虽然这个解决方案/黑客“有效”,但它似乎并没有禁用缓冲,这是我的问题。

    更新:我发现这个 hack 在 Safari 中不起作用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-03
      • 1970-01-01
      • 1970-01-01
      • 2012-04-12
      相关资源
      最近更新 更多