php--->php 缓冲区 buffer 原理
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()函数是无法起作用的。
- 1、apache buffer
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.辨析
ob_end_flush()与ob_end_clean()区别
- 这两个函数都会关闭输出缓冲。
- 不同的是,ob_end_flush()只是把PHP缓冲区中的数据发送到客户端浏览器,而ob_clean_clean()将PHP缓冲区中的数据删除,但不发送给客户端。ob_end_flush()调用之后,PHP缓冲区中的数据依然存在,ob_get_contents()依然可以获取PHP缓冲区中的数据拷贝。
flush()和ob_flush()
- 参考:https://www.cnblogs.com/phpper/p/7750104.html
- 这两个函数的使用怕是很多人最迷惑的一个问题,手册上对两个函数的解释也语焉不详,没有明确的指出它们的区别,似乎二者的功能都是刷新输出缓存。但在我们文章一开始的代码中如果讲fush()替换成ob_flush(),程序就再不能正确执行了。显然,它们是有区别的,否则也手册中直接说明其中一个是另外一个函数的别名即可了,没必要分别说明。那么它们的区别到底是什么呢?
- 反复研究了手册的说明,参考了手册中一些人的留言,自己琢磨应该是这样的: 在没有开启缓存时,脚本输出的内容都在服务器端处于等待输出的状态,flush()可以将等待输出的内容立即发送到客户端。 开启缓存后,脚本输出的内容存入了输出缓存中,这时没有处于等待输出状态的内容,你直接使用flush()不会向客户端发出任何内容。而ob_flush()的作用就是将本来存在输出缓存中的内容取出来,设置为等待输出状态,但不会直接发送到客户端,这时你就需要先使用ob_flush()再使用flush(),客户端才能立即获得脚本的输出。
php--->php 缓冲区 buffer 原理的更多相关文章
- 双缓冲(Double Buffer)原理和使用
转自双缓冲(Double Buffer)原理和使用 一.双缓冲作用 双缓冲甚至是多缓冲,在许多情况下都很有用.一般需要使用双缓冲区的地方都是由于"生产者"和& ...
- Java NIO 缓冲区 Buffer
缓冲区 Buffer 是 Java NIO 中一个核心概念,它是一个线性结构,容量有限,存放原始类型数据(boolean 除外)的容器. 1. Buffer 中可以存放的数据类型 java.nio.B ...
- Java-NIO(二):缓冲区(Buffer)的数据存取
缓冲区(Buffer): 一个用于特定基本数据类行的容器.有java.nio包定义的,所有缓冲区都是抽象类Buffer的子类. Java NIO中的Buffer主要用于与NIO通道进行交互,数据是从通 ...
- 缓冲区(buffer)与缓存(cache)
下面介绍缓冲区的知识. 一.什么是缓冲区 缓冲区(buffer),它是内存空间的一部分.也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区, ...
- NIO(一)——缓冲区Buffer
NIO(一)--Buffer NIO简介 NIO即New IO,是用来代替标准IO的,提供了与标准IO完全不同传输方式. 核心: ...
- Java NIO4:缓冲区Buffer(续)
一.什么是缓冲区 一个缓冲区对象是固定数量的数据的容器,其作用是一个存储器,或者分段运输区,在这里数据可被存储并在之后用于检索.缓冲区像前篇文章讨论的那样被写满和释放,对于每个非布尔原始数据 ...
- Java NIO3:缓冲区Buffer
在上一篇中,我们介绍了NIO中的两个核心对象:缓冲区和通道,在谈到缓冲区时,我们说缓冲区对象本质上是一个数组,但它其实是一个特殊的数组,缓冲区对象内置了一些机制,能够跟踪和记录缓冲区的状态变化情况,如 ...
- Java NIO -- 缓冲区(Buffer)的数据存取
缓冲区(Buffer): 一个用于特定基本数据类型的容器.由 java.nio 包定义的,所有缓冲区都是 Buffer 抽象类的子类.Java NIO 中的 Buffer 主要用于与 NIO 通道进行 ...
- NIO之缓冲区(Buffer)的数据存取
缓冲区(Buffer) 一个用于特定基本数据类行的容器.有java.nio包定义的,所有缓冲区都是抽象类Buffer的子类. Java NIO中的Buffer主要用于与NIO通道进行交互,数据是从通道 ...
随机推荐
- Python反射笔记
通过字符串的形式,导入模块.使用__import__ In [3]: SYS = __import__("sys") In [4]: SYS.path 如果导入模块在多级文件夹下 ...
- DEVOPS技术实践_23:判断文件下载成功作为执行条件
在实际生产中,我们经常会需要通过判断一个结果作为一个条件去执行另一个内容,比如判断一个文件是否存在,判官一个命令是否执行成功等等 现在我们选择其中一个场景进行实验,当某个目录下存在,则执行操作 1. ...
- Autofac总结
Autofac 介绍|术语 控制反转:IOC和DI IOC 调用者不再创建(不自己new)被调用者的实例,而是交给容器去创建(AutoFac就充当这里的容器),这就是控制反转 控制反转中引入的第三方对 ...
- $Poj1821\ Fence\ $单调队列优化$DP$
Poj Acwing Description 有N块木板等待被M个工匠粉刷,每块木板至多被刷一次.第i个工匠要么不粉刷,要么粉刷包含木块Si的,长度不超过Li的连续的一段木板,每粉刷一块可以得到P ...
- [gitHub实践] git基础:远程仓库的使用
[gitHub实践] git基础:远程仓库的使用 版权2019.6.2更新 git 基础 远程仓库的使用 git remote # 查看远程仓库 $ git remote # 克隆的仓库服务器默认名字 ...
- Linux下离线安装gdb及常用命令汇总
以redhat6.5虚拟机作为例子,由于工作性质,大部分情况linux的软件安装,是采用离线方式的. 1.离线安装gdb 像gcc.g++或者gdb这种常用的工具软件,一般虚拟机都会安装的,如未安装, ...
- 线程池:ThreadPoolExecutor的使用
ThreadPoolExecutor配置 一.ThreadPoolExcutor为一些Executor提供了基本的实现,这些Executor是由Executors中的工厂 newCahceThread ...
- Java截图小程序源码
Java编写的全屏截图小程序 package cnom.test.testUtils; import java.awt.AWTException; import java.awt.Dimension; ...
- ACM北大暑期课培训第五天
今天讲的扫描线,树状数组,并查集还有前缀树. 扫描线 扫描线的思路:使用一条垂直于X轴的直线,从左到右来扫描这个图形,明显,只有在碰到矩形的左边界或者右边界的时候,这个线段所扫描到的情况才会改变, ...
- Linux学习_菜鸟教程_2
Linux 系统目录 /bin: bin是Binary的缩写,这个目录存放着最经常使用的命令. /boot: 存放启动Linux时的一些核心文件,包括一些连接文件以及镜像文件. /dev : de ...