我在nginx/1.14.1服务器上使用CodeIgniter 3 PHP框架,带有PHP/7.4.19。
我正在尝试设置事件流。控制器方法看起来是这样的:
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: pingn";
$output .= "id: $random_stringn";
$output .= "data: ";
$output .= json_encode($array);
$output .= "nn";
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脚本时,它可以正常工作。
我能够在Chrome中通过在回声输出之前添加行$output .= str_pad('', 4096) . "nn";
来实现所需的结果。
然而,尽管这种解决方案/破解";作品";,它似乎并没有禁用缓冲,这就是我的问题所在。
更新:我发现这个黑客在Safari中不起作用。
我想知道这是否是Nginx的问题?我在Nginx后面运行服务器发送事件时也遇到了类似的问题。修复方法是在响应中添加值为"no"的"X-Accel-Buffering"标头。