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_自定义关键字的使用
1.在Python中新建一个套件MOSAPP(一般为APP名称):New Suite→Directory 2.在套件下新建个资源文件My:New Resource:My 3.在My资源文件库下新建个关 ...
- 第二阶段:2.商业需求分析及BRD:7.商业需求文档3
BRD模版 阐述需求来源以及调研分析情况 百度指数工具.定量的数据.发展趋势,是否与公司的战略冲突.环境政策:比如做内容的运营. 决策层看重的! 第二大块. 通过什么方式解决这个需求. 规划能力.类似 ...
- 记springboot + MP +Hikari动态数据源配置
环境准备: springboot 2.1.6 mybatis-plus 数据库驱动 boot 自带hikari驱动 步骤1: 导入多数据源启动工具类 <!-- 多数据源支持 -->< ...
- Java程序员必备:异常的十个关键知识点
前言 总结了Java异常十个关键知识点,面试或者工作中都有用哦,加油. 一. 异常是什么 异常是指阻止当前方法或作用域继续执行的问题.比如你读取的文件不存在,数组越界,进行除法时,除数为0等都会导致异 ...
- 记一次ftp错误
在一个ftp上,突然登不上 报错,使用浏览器登录,报此用户不是私密连接,然后使用服务器客户端登录尝试,错误信息如下: [root@test ~]# ftp *.*.*.* Connected to * ...
- 利用Python实现高度定制专属RSS
前言 本文转载自个人博客网站,欢迎来访订阅.本篇属于定制RSS系列终极一弹,是三种方式中自由度最高.定制化最强的,也需要一定的编程能力.附上前两篇链接:1.利用Feed43为网站自制RSS源:2.如何 ...
- 使用vue-quill-editor富文本 实现图片上传
1. 下载并引入 import { quillEditor, Quill } from "vue-quill-editor"; import { container, ImageE ...
- Codeforces Round #519 by Botan Investments(前五题题解)
开个新号打打codeforces(以前那号玩废了),结果就遇到了这么难一套.touristD题用了map,被卡掉了(其实是对cf的评测机过分自信),G题没过, 700多行代码,码力惊人.关键是这次to ...
- Activity启动过程源码分析(Android 8.0)
Activity启动过程源码分析 本文来Activity的启动流程,一般我们都是通过startActivity或startActivityForResult来启动目标activity,那么我们就由此出 ...
- Tomcat黑窗口中对于中文乱码问题的解决
存在的问题: 如标题,下图所示,启动tomcat时黑窗口中中文乱码,影响查看程序打印信息 解决方案: tomcat安装/解压目录中,conf 文件夹下 logging.properties 文件中,代 ...