php 缓冲区 buffer 原理
1.缓冲流程
- 从php脚本echo(print、print_r...)内容之后,是如何显示给用户的呢,下面看看流程
echo、print => php output_buffering => webServer buffer => browser buff => browser display
//即:脚本输出 => php的缓冲区设置 => 系统的缓冲区设置(apache、nginx) => 浏览器的缓冲区设置 => 显示给用户
2. php buffer
- php运行的结果先放入缓冲区(buffer),只有当缓冲区满了或者php运行完毕,才将数据输出去。
- 缓冲区是通过php.ini中的output_buffering变量控制,可以设置大于0的数值来打开buffer。
- ob_start()手动激活php output_buffering机制,使得即便输出超过了4kb数据,也不把数据交给tcp传给浏览器,因为ob_start()将php buffer空间设置到了足够大 。只有直到脚本结束,或者调用ob_end_flush函数,才会把数据发送给客户端浏览器。需要注意的是php.ini中php buffer是关闭的,再次调用ob_end_flush()会报warning。
3.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()函数是无法起作用的。
4.browser buffer
- IE为256Bytes, Chrome与FireFox为1000Bytes,只有输出数据达到了这个长度或者脚本结束浏览器才会将数据输出在页面上。
- 在 php端无法关闭浏览器buffer。
为了使得数据及时输出,可以在发送真正内容 数据前,发送一些空格来填满浏览器的buffer。
浏览器的buffer一满,就会将其他新输出的数据输出。
但是不同的浏览器会设置不同的buffer大小。
为了保险期间,可以发送4096个空格,因为目前比较流行的浏览器的buffer还没有超过4k(一个内页大小)。
5.输出缓冲区相关函数主要有:
ob_start() - 打开输出控制缓冲
ob_get_length() - 返回输出缓冲区的长度
ob_get_level() - 返回输出缓冲区的嵌套级别
ob_get_status() - 返回输出缓冲区的状态(数组形式返回,默认返回最顶层,参数为true时返回所有)
ob_get_contents() - 返回输出缓冲区的内容
ob_get_clean() - 以字符串格式返回当前输出缓冲区并关闭输出缓冲
ob_end_clean() - 清空(擦除)缓冲区并关闭输出缓冲
ob_get_flush() - 以字符串返回输出缓冲区内容并关闭缓冲
ob_end_flush() - 冲刷出(送出)输出缓冲区内容缓冲并关闭输出缓冲
6.辨析
|
请发表评论