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. 假期汇总表handler中涉及的基础知识

    1,stringBuffer 的常用方法,append () 方法, public StringBuffer append(boolean b) 追加内容到当前StringBuffer对象的末尾 ,我 ...

  2. Java泛型类特性

    在2004年末Java推出了Java5,其中提供了对泛型方法和类的支持,也围绕着泛型推出了一下特性,本章将对Java泛型进行综合的概括 1.泛型特性构件pre-Java 5 1.使用Object表示泛 ...

  3. 【题解/模板】P1248 加工生产调度(贪心)

    [题解/模板]P1248 加工生产调度(贪心) 分析: \(A\)流水线的时间是确定的,所以现在就是要让\(b\)的时间尽量短 \(tB > tA\),除非所有东西都不需要\(b\).(t指结束 ...

  4. IDEA启动报错Internal error. Please report to http://jb.gg/ide/critical-startup-errors java.lang.NoClassDefFoundError: org/eclipse/xtext/xbase/lib/Exceptions

    报错内容: IDEA 启动报错 Internal error. Please report to http://jb.gg/ide/critical-startup-errors 报错图为: 我尝试找 ...

  5. 跌宕起伏的java帝国史,剖析谷歌甲骨文长达8年的版权战争

    这篇博文是我在B站上发的一个科普java的视频文案整理,本来发过一次了,但是有几种不严谨的地方只能删掉重新发了一下,内容如标题,感兴趣的码农朋友可以观看视频的版本,欢迎提提意见啥的,感谢~https: ...

  6. 「洛谷P1233」木棍加工 解题报告

    P1233 木棍加工 题目描述 一堆木头棍子共有n根,每根棍子的长度和宽度都是已知的.棍子可以被一台机器一个接一个地加工.机器处理一根棍子之前需要准备时间.准备时间是这样定义的: 第一根棍子的准备时间 ...

  7. 基于CentOS 7 部署MySQL 5.7的基本操作

    关闭selinux # sed -i '/SELINUX/s/enforcing/disabled/' /etc/selinux/config重启后生效# sestatus 修改提示符配置# vi / ...

  8. mongodb 更新嵌套数组的值

    概要 本文主要讲述在 mongodb 中,怎么更新嵌套数组的值. 使用$更新数组 基本语法  { "<array>.$" : value } 可以用于:update, ...

  9. 再也不怕和老外交流了!我用python实现一个微信聊天翻译助手!

    前言 在前面的一篇文章如何用python“优雅的”调用有道翻译中咱们清楚的写过如何一层一层的解开有道翻译的面纱,并且笔者说过那只是脑洞的开始.现在笔者又回来了.当你遇到一些外国小哥哥小姐姐很心动.想结 ...

  10. python之字符串的简单应用

    1.实现5+7加法运算 value = input(">>>") v1, v2 = value.split('+') c1 = int(v1) c2 = int( ...