PHP 缓冲区 ob_flush() 与 flush()
Posted
技术标签:
【中文标题】PHP 缓冲区 ob_flush() 与 flush()【英文标题】:PHP buffer ob_flush() vs. flush() 【发布时间】:2011-05-10 15:14:31 【问题描述】:ob_flush()
和 flush()
之间有什么区别,为什么我必须同时调用这两个?
ob_flush()
reference 说:
此函数将发送输出缓冲区的内容(如果有)。
flush()
reference 说:
刷新 php 的写入缓冲区以及 PHP 正在使用的任何后端(CGI、Web 服务器等)。
但是,它继续说:
[it] 可能无法覆盖您的 Web 服务器的缓冲方案...
所以,在我看来,我可以一直使用ob_flush()
。但是,当我这样做时,我会得到奇怪的结果。有人可以简单地解释一下这里发生了什么吗?
【问题讨论】:
【参考方案1】:ob_flush
发送一个应用程序启动的缓冲区。在任何 PHP 脚本中可能有多个嵌套的ob_start()
。 ob_flush
将当前内容传递给上层。
PHP 本身可能(自行决定)缓冲输出。这取决于后端。但通常FastCGI
有自己的套接字缓冲区。因此还需要调用flush()
将当前内容发送到Web 服务器。
现在,Web 服务器本身可能会实现另一个缓冲方案(mod_deflate
或内容过滤器),您对此没有任何影响。但这很少见,因为需要专门配置。
不管怎样,两者都用。
【讨论】:
使用 ob_flush 和 flush 并按顺序使用它们。 这个答案中缺少的重要细节是output_buffering
配置选项,其在生产版本的 php.ini 中的默认值为 4096。这意味着当任何 PHP 脚本启动时,前 4096 个字节输出被缓冲(在可使用ob_flush()
刷新的缓冲区中)。这就是为什么必须使用ob_flush()
和flush()
的原因。通过 php.ini 禁用 output_buffering
或在脚本开头调用 ob_end_clean()
或 ob_end_flush()
消除了这种必要性。
感谢@MarkAmery,但“脚本开头”处的ob_end_clean()
似乎违反直觉。你的意思是我们应该在ob_start()
之后和两次刷新之前包括这个?
好吧,我在脚本的开头有一个ob_start()
和一个ob_end_clean()
。然后在脚本期间的任何“回声”之后,我还包括ob_flush(); flush();
,我希望在脚本花费时间的同时,到目前为止所做的任何事情都会输出到屏幕上(在浏览器中)。但是直到最后什么都没有。我错过了什么?
@KhomNazid 浏览器观察与调试 HTTP 流不同。对不完整 html DOM 的增量和延迟输出不太可能是可见的。使用您当前的设置进行一些 CLI 测试。 (然后,并且只有在那时,开始一个不同的问题。)【参考方案2】:
ob_flush
刷新使用ob_start
等函数创建的输出缓冲区你
flush
将 PHP 脚本本身的缓冲输出刷新给调用者
【讨论】:
【参考方案3】:ob_flush()
是高级刷新。它刷新高级缓冲区并将所有内容放入准备发送的低级内部缓冲区。
ob_
系列函数会创建 堆栈 缓冲区,因此如果编写代码是为了利用这一优势,只是盲目地到处写 ob_flush()
确实会给您带来“奇怪的结果”这种堆叠。
flush()
是低级刷新,指示 PHP 刷新其内部的低级数据缓冲区。
在此之下,还有套接字层缓冲区;在此之下,有网络层缓冲区。并且,在最低层,沿着数据电缆向下的电子队列。
【讨论】:
好吧,我在脚本的开头有一个ob_start()
和一个ob_end_clean()
。然后在脚本期间的任何“回声”之后,我还包括ob_flush(); flush();
,并且我希望在脚本花费时间的同时,到目前为止所做的任何事情都会输出到屏幕上(在浏览器中)。但是直到最后什么都没有。我错过了什么?
@KhomNazid 按中间阶段缓冲,例如网络服务器、代理、浏览器...【参考方案4】:
我猜这与您的previous question 有关。使用输出缓冲的显着优势在于它与数据压缩一起使用。如果您不使用ob_gzhandler
,则几乎没有什么收获。 flush
将仅提交仍在服务器上的任何输出数据。使用ob_start
及其对应的ob_flush
、ob_end_clean
和ob_end_flush
,任何等待压缩的内容(查看flush
和ob_flush
指代不同的存储桶-ob
将数据发送到flush
, flush
将数据发送到浏览器 - 可能不准确,但这就是想法)将被打包并发送到客户端。
【讨论】:
谢谢,桶类比是一个很好的例子。以上是关于PHP 缓冲区 ob_flush() 与 flush()的主要内容,如果未能解决你的问题,请参考以下文章
PHP IIS 环境 ob_flush()刷新缓冲区执行完才显示 解决办法,iis缓冲区原因
ob_flush()和flush()和ob_implicit_flush(true)