PHP实时输出内容到浏览器

buffer

是一个内存地址空间, Linux 系统默认大小一般为 4096(4kb) ,即一个内存页。主要用于存储速度不同步的设备或者优先级不同的设备之间传办理数据的区域。通过 buffer,可以使进程这间的相互等待变少。这里说一个通俗一点的例子,你打开文本编辑器编辑一个文件的时候,你每输入一个字符,操作系统并不会立即把这个字符直接写入到磁盘,而是先写入到buffer,当写满了一个 buffer 的时候,才会把 buffer 中的数据写入磁盘,当然当调用内核函数 flush() 的时候,强制要求把 buffer 中的脏数据写回磁盘。

同样的道理,当执行 echo,print 的时候,输出并没有立即通过 tcp 传给客户端浏览器显示, 而是将数据写入 php bufferphp output_buffering 机制,意味在 tcp buffer 之前,建立了一新的队列,数据必须经过该队列。当一个 php buffer写满的时候,脚本进程会将 php buffer 中的输出数据交给系统内核交由 tcp 传给浏览器显示。所以,数据会依次写到这几个地方:echo/print -> php buffer -> tcp buffer -> browser


php output_buffering

默认情况下,php buffer 是开启的,而且该 buffer 默认值是 4096,即 4kb。你可以通过在 php.ini 配置文件中找到 output_buffering 配置.当 echo,print 等输出用户数据的时候,输出数据都会写入到 php output_buffering 中,直到 output_buffering 写满,会将这些数据通过 tcp 传送给浏览器显示。你也可以通过 ob_start() 手动激活 php output_buffering 机制,使得即便输出超过了 4kb 数据,也不真的把数据交给 tcp 传给浏览器,因为 ob_start()php buffer 空间设置到了足够大。只有直到脚本结束,或者调用 ob_end_flush 函数,才会把数据发送给客户端浏览器。

php配置 (与Apache服务器有关)

1
2
3
4
implicit_flush = off
output_buffering = off

php output_buffering

默认情况下,php buffer是开启的,而且该 buffer 默认值是 4096,即 4kb。你可以通过在 php.ini 配置文件中找到output_buffering配置.当 echo,print 等输出用户数据的时候,输出数据都会写入到 php output_buffering 中,直到 output_buffering 写满,会将这些数据通过 tcp 传送给浏览器显示。你也可以通过 ob_start() 手动激活 php output_buffering 机制,使得即便输出超过了 4kb 数据,也不真的把数据交给 tcp 传给浏览器,因为 ob_start()php buffer 空间设置到了足够大。只有直到脚本结束,或者调用 ob_end_flush 函数,才会把数据发送给客户端浏览器。


有关header,服务器为nginx的时候需要开启

1
2
3
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('X-Accel-Buffering: no');

下面是一个例子(实现服务器 nginx):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function foo() 
{
header( 'Content-Type: text/event-stream' );
header( 'Cache-Control: no-cache' );
header( 'X-Accel-Buffering: no' );

$i = 0;
do {
echo $i . "\n";
$i ++;
ob_flush();
flush();
//ob_end_flush();
sleep( 1 );
} while ( $i < 1000 );

exit( 'done' );
}
Author: rexmolo
Link: http://rexmolo.github.io/2018/07/06/php-implicit-flush/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.