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.辨析
  • 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 原理的更多相关文章

  1. 双缓冲(Double Buffer)原理和使用

    转自双缓冲(Double Buffer)原理和使用 一.双缓冲作用            双缓冲甚至是多缓冲,在许多情况下都很有用.一般需要使用双缓冲区的地方都是由于"生产者"和& ...

  2. Java NIO 缓冲区 Buffer

    缓冲区 Buffer 是 Java NIO 中一个核心概念,它是一个线性结构,容量有限,存放原始类型数据(boolean 除外)的容器. 1. Buffer 中可以存放的数据类型 java.nio.B ...

  3. Java-NIO(二):缓冲区(Buffer)的数据存取

    缓冲区(Buffer): 一个用于特定基本数据类行的容器.有java.nio包定义的,所有缓冲区都是抽象类Buffer的子类. Java NIO中的Buffer主要用于与NIO通道进行交互,数据是从通 ...

  4. 缓冲区(buffer)与缓存(cache)

    下面介绍缓冲区的知识. 一.什么是缓冲区 缓冲区(buffer),它是内存空间的一部分.也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区, ...

  5. NIO(一)——缓冲区Buffer

                                        NIO(一)--Buffer NIO简介 NIO即New IO,是用来代替标准IO的,提供了与标准IO完全不同传输方式. 核心: ...

  6. Java NIO4:缓冲区Buffer(续)

    一.什么是缓冲区      一个缓冲区对象是固定数量的数据的容器,其作用是一个存储器,或者分段运输区,在这里数据可被存储并在之后用于检索.缓冲区像前篇文章讨论的那样被写满和释放,对于每个非布尔原始数据 ...

  7. Java NIO3:缓冲区Buffer

    在上一篇中,我们介绍了NIO中的两个核心对象:缓冲区和通道,在谈到缓冲区时,我们说缓冲区对象本质上是一个数组,但它其实是一个特殊的数组,缓冲区对象内置了一些机制,能够跟踪和记录缓冲区的状态变化情况,如 ...

  8. Java NIO -- 缓冲区(Buffer)的数据存取

    缓冲区(Buffer): 一个用于特定基本数据类型的容器.由 java.nio 包定义的,所有缓冲区都是 Buffer 抽象类的子类.Java NIO 中的 Buffer 主要用于与 NIO 通道进行 ...

  9. NIO之缓冲区(Buffer)的数据存取

    缓冲区(Buffer) 一个用于特定基本数据类行的容器.有java.nio包定义的,所有缓冲区都是抽象类Buffer的子类. Java NIO中的Buffer主要用于与NIO通道进行交互,数据是从通道 ...

随机推荐

  1. python3中map函数

    map函数是Python里面比较重要的函数 map函数后面必须接的是序列(元组/列表/字符串) 在python2中执行一些语句 >>> map(str,[1,2,3,4]) ['1' ...

  2. Python反射笔记

    通过字符串的形式,导入模块.使用__import__ In [3]: SYS = __import__("sys") In [4]: SYS.path 如果导入模块在多级文件夹下 ...

  3. 超简单!pytorch入门教程(二):Autograd

    一.autograd自动微分 autograd是专门为了BP算法设计的,所以这autograd只对输出值为标量的有用,因为损失函数的输出是一个标量.如果y是一个向量,那么backward()函数就会失 ...

  4. Java中的循环结构

    1.while循环结构 语法: while(循环条件){ //循环操作 } while循环结构流程图: 举例: int i = 1; while(i <= 100){ System.out.pr ...

  5. Java程序员必备:异常的十个关键知识点

    前言 总结了Java异常十个关键知识点,面试或者工作中都有用哦,加油. 一. 异常是什么 异常是指阻止当前方法或作用域继续执行的问题.比如你读取的文件不存在,数组越界,进行除法时,除数为0等都会导致异 ...

  6. 003 ansible部署ceph集群

    介绍:在上一次的deploy部署ceph,虽然出了结果,最后的结果并没有满足最初的目的,现在尝试使用ansible部署一遍,看是否会有问题 一.环境准备 ceph1充当部署节点,ceph2,ceph3 ...

  7. 【题解】SDOI2015序列统计

    [题解]SDOI2015序列统计 来自永不AFO的YYB的推荐 这里是乘积,比较麻烦,不过由于给定的序列膜数是个小质数,所以可以\(O(m^2\log m)\)找原跟(实际上不需要这么多). 乘积有点 ...

  8. $[NOIp2017]$ 宝藏 状压$dp$

    \(Sol\) 觉得这里是个很巧妙的地方吖,就是记下当前扩展点集的最大深度,然后强制下一步扩展的点集都是最大深度+1.这样做在当前看可能会导致误算答案导致答案偏大,但是整个\(dp\)完成后一定可以得 ...

  9. 菜鸟系列Fabric源码学习 — MVCC验证

    Fabric 1.4 源码分析 MVCC验证 读本节文档之前建议先查看[Fabric 1.4 源码分析 committer记账节点]章节. 1. MVCC简介 Multi-Version Concur ...

  10. 《美国纽约摄影学院摄影教材》PDF教材

        下载地址: 美国纽约摄影学院摄影教材(上册).pdf 美国纽约摄影学院摄影教材(下册).pdf 欢迎你到纽约摄影学院来,我们急切地等待着开课,你们也在 跃跃欲试了.那就让我们马上开始吧! 你已 ...