LEN

【转】 PHP输出缓冲 -- 缓冲区原理
从php脚本echo(print、print_r...)内容之后,是如何显示给用户的呢,下面看看流程echo、pr...
扫描右侧二维码阅读全文
24
2017/11

【转】 PHP输出缓冲 -- 缓冲区原理

从php脚本echo(print、print_r...)内容之后,是如何显示给用户的呢,下面看看流程
echo、print => php output_buffering => webServer buffer => browser buff => browser display
即:脚本输出 => php的缓冲区设置 => 系统的缓冲区设置(apache、nginx) => 浏览器的缓冲区设置 => 显示给用户

php buffer

php运行的结果先放入缓冲区(buffer),只有当缓冲区满了或者php运行完毕,才将数据输出去。
缓冲区是通过php.ini中的output_buffering变量控制。output_buffering的默认值是off,可以设置大于0的数值来打开buffer。具体介绍
但是这里需要注意的是:
1)使用ini_set是无法修改buffer的设置。
2)不管php.ini中output_buffering设置,cli模式下的php始终默认是output buffering为关闭的。但是你可以通过ob_start()将buffer打开。
大家都说:ob_start()是将php buffer打开,ob_end_flush()是将php buffer关闭。需要注意的是php.ini中php buffer是关闭的,再次调用ob_end_flush()会报warning。

webServer buffer

这里主要讲apache和nginx的缓冲区。
1、apache buffer
当php的输出数据给apache服务器时,它也会做一层buffer(也将数据放入它的缓冲区,当缓冲区数据满或执行完毕时,才输出数据)。
若想关闭缓冲区,可以在php层使用flush()来强制将缓冲区数据输出。
fulsh() 的工作原理:在apache module的sapi下, flush会通过调用sapi_module的flush成员函数指针, 间接的调用apache的api: ap_rflush刷新apache的输出缓冲区, 当然手册中也说了, 有一些apache的其他模块, 可能会改变这个动作的结果.例如mod_gzip,可能自己进行输出缓冲区,这将导致flush()函数产生的结果不会立即被发送到客户端浏览器。

2、nginx buffer
nginx使用fastcgi缓冲区来缓冲数据。很遗憾的是,fastcgi是强制将buffer打开的,无法关闭缓冲区。
有人有可能会想,无法关闭可以将buffer设置的足够小,来使缓冲数据输出,达到无缓冲的效果。但是这个想法无法实现。
原因一:fastcgi buffer无法识别小于1k的数值。
原因二:受参数之间大小关系的影响。

具体可以看看fastcgi的一些buffer设置。
fastcgi_buffer_size:用来存储response的header数据。
fastcgi_buffers:用来存储response的内容数据.
fastcgi_busy_buffers_size:用来控制同时传输到客户端的buffer数量。一旦fastcgi_buffers设置的 buffer被写入,直到buffer里面的数据被完整的传输完(传输到客户端),这些buffer将会一直处在busy状态,我们不能对这些 buffer进行任何别的操作。所有处在busy状态的buffer size加起来不能超过fastcgi_busy_buffers_size。

参数之间大小关系:

fastcgi_busy_buffers_size < (all fastcgi_buffers – one buffer) 并且fastcgi_busy_buffers_size>=max (fastcgi_buffer_size, one fastcgi _buffers)。
例如,在nginx.conf配置中有:
fastcgi_buffers 4 128k
fastcgi_buffer_size 256k

那么fastcgi_busy_buffers_size<(4*128k – 4k) 并且fastcgi_busy_buffers_size>=max(256k, 128k)
其中,4k(one buffer的大小)是linux系统默认的缓存大小,即一个内存页。
若fastcgi_buffer_size设置的很小,会导致header过小的错误。你也同样无法保证设置的值会满足所有的情况。

要注意的是:
flush, 严格来讲, 这个只有在PHP做为apache的Module(handler或者filter)安装的时候, 才有实际作用. 它是刷新WebServer(可以认为特指apache)的缓冲区.所以在nginx下,flush()函数是无法起作用的。

browser buffer

IE为256Bytes, Chrome与FireFox为1000Bytes,只有输出数据达到了这个长度或者脚本结束浏览器才会将数据输出在页面上。
在 php端无法关闭浏览器buffer。
为了使得数据及时输出,可以在发送真正内容 数据前,发送一些空格来填满浏览器的buffer。
浏览器的buffer一满,就会将其他新输出的数据输出。
但是不同的浏览器会设置不同的buffer大小。
为了保险期间,可以发送4096个空格,因为目前比较流行的浏览器的buffer还没有超过4k(一个内页大小)。

原文地址: http://blog.csdn.net/fwkjdaghappy1/article/details/25402809

Last modification:November 24th, 2017 at 11:32 am
If you think my article is useful to you, please feel free to appreciate

Leave a Comment