原文地址: http://www.php20.cn/article/sw/buffer/104

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
  
#1. 我们再浏览器发起请求时,php输出流程如下:
php echo | print_r() >> php output_buffering >> webServer buffer   >> browser buff >> browser display
既:
php输出语句/函数      >> php缓冲区配置         >> web服务器缓冲区配置 >> 浏览器缓冲区  >> 浏览器显示
 
#2. php的配置:output_buffering
php缓冲区配置主要由php.ini 中的output_buffering配置的,默认情况下: output_buffering=4096
当php输出数据时,输出的数据将会先经过output_buffering中,直到数据大于output_buffering配置的值或者php文件执行完毕, 才会将数据输出
 
#3. 下面是一个代码示例 demo.php
//---------------------------------------文件内容如下    begin
$i = 10;
 
//开启 buffer 缓存区(php-cli)下默认是关闭缓存区的,所以我们这里需要提前开启
ob_start();
 
while ($i) {
    echo $i . "\n\r";
    if ($i % 2 == 0) {
        sleep(1);
        echo 'Time:' . microtime(true) . "\n\r";
        ob_end_flush();
        ob_start();
    }
    $i--;
}
echo 'ok';
#在开启缓存区的情况下,先输出$i,如果$i为偶数则睡眠一秒钟然后输出当前微秒数
//---------------------------------------文件内容如下    end
 
#4. 运行测试结果
> php demo.php
//---------------------------------------输出结果如下     begin
#运行结果: 不管是奇数还是偶数都是与Time同时输出的,既.只有关闭缓存区的情况下才会输出
10
Time:1543820692.1241
9
8
Time:1543820693.1246
7
6
Time:1543820694.1249
5
4
Time:1543820695.1251
3
2
Time:1543820696.1253
1
ok
 
//---------------------------------------输出结果如下     end
 
#5. 说明:
当在web访问时,php默认开启4096的缓冲区,当里面存取的字符串长度超过时,将会进行一次输出到web服务器.
可通过 ob_start() 和 ob_end_flush() 进行直接的缓冲区控制(此间将会无视output_buffering的值).
 
 
#6. 注意:
1). php-cli默认关闭缓冲区并且无视output_buffering的值,需要通过 ob_start() 函数进行打开
2). ini_set无法修改output_buffering的配置
3). 当php.ini中php buffer是关闭的,再次调用 ob_end_flush() 会报warning.
4). 至于为什么web浏览器不能查看到分段输出的值,原因为: web服务器还有一次缓冲区
 
 
另.附上: web服务器分段响应数据
 
7. Apache 分段输出
# 高版本下apache默认开启buffer,可通过配置httpd.conf,设置FcgidOutputBufferSize 0来保证不缓存
//--------------------------------文件内容  begin
for($i=0;$i<1000;$i++){
    echo $i;
 
    ob_flush();//刷新PHP自身缓冲区
 
    flush();//刷新(特指apache)web服务器的缓冲区,输出数据
 
    sleep(1);
}
//--------------------------------文件内容  end
 
8. Nginx 分段输出
//--------------------------------文件内容  begin
set_time_limit(0);
ob_end_clean();
ob_implicit_flush();
header('X-Accel-Buffering: no'); // 关键是加了这一行。
for($i=0;$i<1000;$i++){
    echo $i;
    sleep(1);
}
//--------------------------------文件内容  end
 
  


---------------------------------------------------------------------------------------------
不忘初心 方得始终!

唯有志存高远,方能风行天下。

道之所存,虽千万人吾往矣! 情之所钟,虽千万里吾念矣~

原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。