问题描述
我在带有 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 脚本时,它按预期工作。
解决方法
通过在回显输出之前添加行 $output .= str_pad('',4096) . "\n\n";
,我能够在 Chrome 中实现所需的结果。
然而,虽然这个解决方案/hack“有效”,但它似乎并没有禁用缓冲,这就是我的问题。
更新:我发现这个 hack 在 Safari 中不起作用。