【发布时间】: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