nginx与PHP的flush(摘抄加总结)
2015-11-07 20:36
555 查看
先看一段代码呗,它的作用是间断性输出
据说apache下是可以的。但nginx下一定不行,nginx下正确步骤如下
1.首先需要设置nginx.conf:
记得重启php和nginx
2.代码部分
然后就可以1s输出一行了
首先看下我查到的资料
buffer是一个内存地址空间,Linux系统默认大小一般为4096(4kb),即一个内存页,可以在终端执行
同样的道理,当执行echo、print的时候,输出并没有立即通过tcp传给客户端浏览器显示,而是将数据写入php buffer。php output_buffering机制,意味在tcp buffer之前,建立了一新的队列,数据必须经过该队列。当一个php buffer写满的时候,脚本进程会将php buffer中的输出数据交给系统内核交由tcp传给浏览器显示。所以,数据会依次写到这几个地方:echo/print -> php buffer -> tcp buffer -> browser
2.php output_buffering
默认情况下,php buffer是开启的,而且该buffer默认值是4096,即4kb。你可以通过在php.ini配置文件中找到output_buffering配置。当echo、print等输出用户数据的时候,输出数据都会写入到php output_buffering中,直到output_buffering写满,会将这些数据通过tcp传送给浏览器显示。你也可以通过ob_start()手动激活php output_buffering机制,使得即便输出超过了4kb数据,也不真的把数据交给tcp传给浏览器,因为ob_start()将php buffer空间设置到了足够大。只有直到脚本结束,或者调用ob_end_flush函数,才会把数据发送给客户端浏览器。
(1)当output_buffering=4096,并且输出较少数据(少于一个buffer)
现象:不是每隔几秒就会有间断性输出,而是直到响应结束,才能一次性看到输出,在等待服务器脚本处理结束之前,浏览器界面一直保持空白。这是因为,数据量太小,php output_buffering没有写满。写数据的顺序,依次是echo->php buffer->tcp buffer->browser
(2)当output_buffering=0,并且输出较少数据(少于一个buffer)
现象:与刚才显示并不一致,禁用了php buffering机制之后,在浏览器可以断断续续看到间断性输出,不必等到脚本执行完毕才看到输出。这是因为,数据没有在php output_buffering中停留。写数据的顺序依次是echo->tcp buffer->browser
(3)当output_buffering=4096,输出数据大于一个buffer,不调用ob_start()
这里我说明下,第一行代码是在命令行创建一个4096大小的文件,然后每次输出
现象:响应还没结束(http连接没有关闭),断断续续可以看到间断性输出,浏览器界面不会一直保持空白。尽管启用了php output_buffering机制,但依然会间断性输出,而不是一次性输出,是因为output_buffering空间不够用。每写满一个php buffering,数据就会发送到客户端浏览器。
(4)当output_buffering=4096, 输出数
4000
据大于一个tcp buffer, 调用ob_start()
现象:直到服务端脚本处理完成,响应结束,才看到完整输,输出间隔时间很短,以至你感受不到停顿。在输出之前,浏览器一直保持着空白界面,等待服务端数据。这是因为,php一旦调用了ob_start()函数,它会将php buffer扩展到足够大,直到ob_end_flush函数调用或者脚本运行结速才发送php buffer中的数据到客户端浏览器。
现象:直到服务端脚本处理完成,响应结束,才看到完整输,输出间隔时间很短,以至你感受不到停顿。在输出之前,浏览器一直保持着空白界面,等待服务端数据。这是因为,php一旦调用了ob_start()函数,它会将php buffer扩展到足够大,直到ob_end_flush函数调用或者脚本运行结速才发送php buffer中的数据到客户端浏览器。
然后笔者看到这里,觉得看懂了output_buffering 也明白了如何实现间断性输出的特效然后就试了下开头部分的第一段代码结果不行。经过多方百度才得写出了第二段代码并实现了效果。所以,以上文字是建立在apache的基础上才有的
文章我抄到这里,原文还有一些其他的东西,在这就不继续赘述了,因为还有别的事,原文地址如下
http://www.jb51.net/article/38363.htm
说到这来叙述下我的开发环境
MAC OX 10.11.1 + NGINX 1.8.0+ PHP 5.6+ PHP-FPM + MYSQL**
现在开始叙述下我的编码过程
一开始
这段代码肯定是不行的,然后就百度,有人说linux环境下
可是还是不行,当然现在才明白,他一定是linux下apache,我mac下nginx,业界良心,在记录问题时应该说下自己的开发环境。然后继续百度当时感觉和nginx有关就带上了nginx关键字:flush在nginx下失效 和 nginx flush 分别进行搜索
然后读到了一篇文章,现摘抄如下
Nginx与php-cgi是两个独立的程序,通过TCP或Unix套接字通信,不像Apache那样是集成在一起的。所以,Nginx 有 fastcgi
缓冲区,数据超出缓冲区大小、或程序执行完,才会将内容输出到客户端。另外,如果要使用ob_flush,不能开启gzip压缩输出。
php.ini:
改为
如果需要连续循环打印的效果,可以加上一行
看到这后,似乎终于明白了什么,于是乎没有理他的代码,在自己的代码上改进,然后修改nginx配置,又出了一版
确实是间断性输出了但是抱错:
然后还是百度,最后在代码开头加上
这就完了?为了出效果算是完了,但是我自己又做了一些尝试。
设置output_buffering
发现代码执行没有影响,难道说nginx环境下,经过以上的配置后可以无视output_buffering 吗?
先记录下来,然后择日再看关于缓冲这块 可能会写出更正确的代码吧
for ($i = 0; $i < 10; $i++) { echo $i.'<br />'; flush(); sleep(1); }
据说apache下是可以的。但nginx下一定不行,nginx下正确步骤如下
1.首先需要设置nginx.conf:
fastcgi_buffer_size 4k; //可以放的位置为 http、server、location fastcgi_buffers 64 4k; //可以放的位置为 http、server、location gzip off; //我只看到过在server段配置
记得重启php和nginx
2.代码部分
<?php ob_start(); for ($i = 0; $i < 10; $i++) { echo $i.'<br />'; echo str_repeat(" ", 1024*4); ob_flush(); flush(); sleep(1); } ?>
然后就可以1s输出一行了
首先看下我查到的资料
先说php缓冲:php.ini 中的 output_buffering
1.bufferbuffer是一个内存地址空间,Linux系统默认大小一般为4096(4kb),即一个内存页,可以在终端执行
getconf PAGESIZE来查看。主要用于存储速度不同步的设备或者优先级不同的设备之间处理数据的区域。通过buffer,可以使进程之间的相互等待变少。这里说一个通俗一点的例子,你打开文本编辑器编辑一个文件的时候,你每输入一个字符,操作系统并不会立即把这个字符直接写入到磁盘,而是先写入到buffer,当写满了一个buffer的时候,才会把buffer中的数据写入磁盘,当然当调用内核函数flush()的时候,强制要求把buffer中的脏数据写回磁盘。
同样的道理,当执行echo、print的时候,输出并没有立即通过tcp传给客户端浏览器显示,而是将数据写入php buffer。php output_buffering机制,意味在tcp buffer之前,建立了一新的队列,数据必须经过该队列。当一个php buffer写满的时候,脚本进程会将php buffer中的输出数据交给系统内核交由tcp传给浏览器显示。所以,数据会依次写到这几个地方:echo/print -> php buffer -> tcp buffer -> browser
2.php output_buffering
默认情况下,php buffer是开启的,而且该buffer默认值是4096,即4kb。你可以通过在php.ini配置文件中找到output_buffering配置。当echo、print等输出用户数据的时候,输出数据都会写入到php output_buffering中,直到output_buffering写满,会将这些数据通过tcp传送给浏览器显示。你也可以通过ob_start()手动激活php output_buffering机制,使得即便输出超过了4kb数据,也不真的把数据交给tcp传给浏览器,因为ob_start()将php buffer空间设置到了足够大。只有直到脚本结束,或者调用ob_end_flush函数,才会把数据发送给客户端浏览器。
(1)当output_buffering=4096,并且输出较少数据(少于一个buffer)
<?php for ($i = 0; $i < 10; $i++) { echo $i . '<br/>'; sleep($i + 1); // } ?>
现象:不是每隔几秒就会有间断性输出,而是直到响应结束,才能一次性看到输出,在等待服务器脚本处理结束之前,浏览器界面一直保持空白。这是因为,数据量太小,php output_buffering没有写满。写数据的顺序,依次是echo->php buffer->tcp buffer->browser
(2)当output_buffering=0,并且输出较少数据(少于一个buffer)
<?php //通过ini_set('output_buffering', 0)并不生效 //应该编辑/etc/php.ini,设置output_buffering=0禁用output buffering机制 //ini_set('output_buffering', 0); //彻底禁用output buffering功能 for ($i = 0; $i < 10; $i++) { echo $i . '<br/>'; flush(); //通知操作系统底层,尽快把数据给客户端浏览器 sleep($i + 1); // } ?>
现象:与刚才显示并不一致,禁用了php buffering机制之后,在浏览器可以断断续续看到间断性输出,不必等到脚本执行完毕才看到输出。这是因为,数据没有在php output_buffering中停留。写数据的顺序依次是echo->tcp buffer->browser
(3)当output_buffering=4096,输出数据大于一个buffer,不调用ob_start()
#//创建一个4kb大小的文件 $dd if=/dev/zero of=f4096 bs=4096 count=1 <?php for ($i = 0; $i < 10; $i++) { echo file_get_contents('./f4096') . $i . '<br/>'; sleep($i +1); } ?>
这里我说明下,第一行代码是在命令行创建一个4096大小的文件,然后每次输出
$i之前现输出这个文件内容,作用就是叫当前echo的内容大于output_buffering设置的值这样就达到输出数据大于一个buffer的效果了。
现象:响应还没结束(http连接没有关闭),断断续续可以看到间断性输出,浏览器界面不会一直保持空白。尽管启用了php output_buffering机制,但依然会间断性输出,而不是一次性输出,是因为output_buffering空间不够用。每写满一个php buffering,数据就会发送到客户端浏览器。
(4)当output_buffering=4096, 输出数
4000
据大于一个tcp buffer, 调用ob_start()
现象:直到服务端脚本处理完成,响应结束,才看到完整输,输出间隔时间很短,以至你感受不到停顿。在输出之前,浏览器一直保持着空白界面,等待服务端数据。这是因为,php一旦调用了ob_start()函数,它会将php buffer扩展到足够大,直到ob_end_flush函数调用或者脚本运行结速才发送php buffer中的数据到客户端浏览器。
<?php ob_start(); //开启php buffer for ($i = 0; $i < 10; $i++) { echo file_get_contents('./f4096') . $i . '<br/>'; sleep($i + 1); } ob_end_flush(); ?>
现象:直到服务端脚本处理完成,响应结束,才看到完整输,输出间隔时间很短,以至你感受不到停顿。在输出之前,浏览器一直保持着空白界面,等待服务端数据。这是因为,php一旦调用了ob_start()函数,它会将php buffer扩展到足够大,直到ob_end_flush函数调用或者脚本运行结速才发送php buffer中的数据到客户端浏览器。
然后笔者看到这里,觉得看懂了output_buffering 也明白了如何实现间断性输出的特效然后就试了下开头部分的第一段代码结果不行。经过多方百度才得写出了第二段代码并实现了效果。所以,以上文字是建立在apache的基础上才有的
文章我抄到这里,原文还有一些其他的东西,在这就不继续赘述了,因为还有别的事,原文地址如下
http://www.jb51.net/article/38363.htm
说到这来叙述下我的开发环境
MAC OX 10.11.1 + NGINX 1.8.0+ PHP 5.6+ PHP-FPM + MYSQL**
现在开始叙述下我的编码过程
一开始
<?php
for ($i = 0; $i < 10; $i++) { echo $i.'<br />'; flush(); sleep(1); }
?>
这段代码肯定是不行的,然后就百度,有人说linux环境下
flush()要和
ob_flush()配合使用,于是有了下面的代码
<?php for ($i = 0; $i < 10; $i++) { echo $i.'<br />'; ob_flush(); flush(); sleep(1); } ?>
可是还是不行,当然现在才明白,他一定是linux下apache,我mac下nginx,业界良心,在记录问题时应该说下自己的开发环境。然后继续百度当时感觉和nginx有关就带上了nginx关键字:flush在nginx下失效 和 nginx flush 分别进行搜索
然后读到了一篇文章,现摘抄如下
nginx与PHP的flush
原文地址 http://www.99n9.com/blog/?p=257Nginx与php-cgi是两个独立的程序,通过TCP或Unix套接字通信,不像Apache那样是集成在一起的。所以,Nginx 有 fastcgi
缓冲区,数据超出缓冲区大小、或程序执行完,才会将内容输出到客户端。另外,如果要使用ob_flush,不能开启gzip压缩输出。
nginx.conf: fastcgi_buffer_size 1k; fastcgi_buffers 4 1k; gzip off;
php.ini:
改为
output_buffering = Off
如果需要连续循环打印的效果,可以加上一行
echo str_repeat("",1024);,使得fastcgi_buffer_size 1k;的缓冲区满,从而输出内容到浏览器:
<?php set_time_limit(0); ob_end_clean(); ob_implicit_flush(1); for($i = 0; $i < 10; $i++){ echo $i, “<br />n”; echo str_repeat(” “,1024); sleep(1); }
看到这后,似乎终于明白了什么,于是乎没有理他的代码,在自己的代码上改进,然后修改nginx配置,又出了一版
<?php for ($i = 0; $i < 10; $i++) { echo $i.'<br />'; echo str_repeat(" ", 1024*4); ob_flush(); flush(); sleep(1); } ?>
确实是间断性输出了但是抱错:
ob_flush(): failed to flush buffer.
然后还是百度,最后在代码开头加上
ob_start();就好了。
这就完了?为了出效果算是完了,但是我自己又做了一些尝试。
设置output_buffering
output_buffering = 4096
发现代码执行没有影响,难道说nginx环境下,经过以上的配置后可以无视output_buffering 吗?
先记录下来,然后择日再看关于缓冲这块 可能会写出更正确的代码吧
相关文章推荐
- Android之使用Http协议实现文件上传功能
- nginx代理指定目录
- 访问Nginx发生SSL connection error的一种情况
- Nginx+Naxsi部署专业级Web应用防火墙
- CentOS 6.2实战部署Nginx+MySQL+PHP
- nginx中http核心模块的配置指令2
- nginx中http核心模块的配置指令3
- nginx中http核心模块的配置指令4
- nginx中http的fastcgi模块的配置指令1
- Nginx 学习笔记(一)
- 网站502与504错误分析
- 网马生成器 MS Internet Explorer XML Parsing Buffer Overflow Exploit (vista) 0day
- 艰难完成 nginx + puma 部署 rails 4的详细记录
- 把Lua编译进nginx步骤方法
- web 应用中常用的各种 cache详解
- 揭秘SQL Server 2014有哪些新特性(2)-固态硬盘 Buffer Pool(缓冲池) 扩展
- Linux系统上配置Nginx+Ruby on Rails+MySQL超攻略
- php中ob(Output Buffer 输出缓冲)函数使用方法
- php中mysql操作buffer用法详解