目的:
定时输出数据到浏览器
运行环境:phpstudy
windows
nginx1.15.11(注意
fastcgi_buffering off
配置,最后讲)
location ~ \.php(.*)$ {
fastcgi_pass 127.0.0.1:9002;
fastcgi_index index.php;
fastcgi_split_path_info ^((?U).+\.php)(/?.+)$;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
include fastcgi_params;
#proxy_buffering off;
fastcgi_buffering off;
}
php7.1.9 (
ini配置
,最后讲)
output_buffering = Off
implicit_flush = On
chrome
实现代码
for($i = 0; $i < 5; $i++)
{
echo "$i<br/>";
sleep(1);
}
php脚本数据输出:
输出过程:
php缓冲区
(可关闭)=> SAPI缓冲区
(无法关闭,只能手动flush刷新或脚本结束自动刷新) =>Nginx缓冲区
(可关闭)=>浏览器缓冲区
(部分浏览器)===>渲染页面,用户可见
流程图(不含浏览器部分):
- 1、
php缓冲区
- 2、
SAPI缓冲区
- 3、
Nginx缓冲区
(output,图中的最下面一层)
PHP缓冲区
- 分类:
用户缓冲区(user output buffers)
:即用户通过调用ob_start()函数打开的输出缓冲区。
默认缓冲区(default output buffers)
:即php默认会打开一个缓冲区,通过output_buffering 来设置,默认为4096,最上面设置output_buffering =Off,就是为了禁用默认缓冲区,使得每次echo都能从PHP缓冲区直接刷新到SAPI缓冲区。- 多层缓冲区:
PHP是支持多层缓冲区嵌套
:可通过多次调用ob_start()来开启多层缓冲区。
堆栈式结构
:即最先开启的缓冲区最后刷新,最后开启的缓冲区最先刷新。比如先后开启了缓冲区A(4k),B(2k),C(1k),输出数据后,首先存入到C的缓冲区,C待自己缓冲区数据大于1k,或者手动刷新ob_flush()后,将数据从C的缓冲区刷新到B的缓冲区,B待自己缓冲区数据大于2k,或这手动刷新后,将数据从B的缓冲区刷新到A的缓冲区,依次类推,最后刷新到SAPI的缓冲区中。
SAPI缓冲区:
sapi种类
:fpm,cli,apache的php模块 等等,这次的例子就是fpm。
数据从PHP缓冲区刷新到SAPI缓冲区的方式
:
- 手动使用ob_flush()等 ob_*方法刷新,注意:如果有多层PHP缓冲区时(比如多次调用ob_start,或者设置了默认缓冲区–也相当于调用了一次ob_start),只会刷新最低一层的PHP缓冲区,如果需要刷新到SAPI缓冲区,就需要多次调用ob_end_flush类函数刷新到最顶一层的缓冲区,一直刷新到SAPI缓冲区中。
- 等待数据达到每一层PHP缓冲区的chunk_size(ob_start函数的参数)值,自动刷新本层缓冲区的数据到上一层缓冲区去。
数据从SAPI缓冲区刷新到nginx的方式
:
- 使用flush()函数
- 设置implicit_flush=On,就是当SAPI缓冲区中有数据时,自动flush()
- 等待脚本结束,自动刷新到web服务器
nginx缓冲区:
数据刷新到nginx等web服务器时,不一定会直接传输到浏览器,他有自己的缓冲区机制,所以测试时关闭nginx的缓冲区才能到浏览器中正常看到结果
- fastcgi_buffering :fpm sapi的缓冲区设置,默认开启
- fastcgi_buffer_size 当fastcgi_buffering 开启时有效
- fastcgi_buffers 当fastcgi_buffering 开启时有效
数据从nginx发送到浏览器后,可能还不能看到定时输出数据的效果,因为部分浏览器有自己的缓存机制,接收到一定大小的数据时才会渲染。可以使用抓包工具查看,或者使用F12功能network 瀑布查看返回数据情况
参考资料:https://gywbd.github.io/posts/2015/1/php-output-buffer-in-deep.html