原文地址: http://www.php20.cn/article/sw/php%E6%8F%90%E5%89%8D%E5%93%8D%E5%BA%94/159

php_buffer缓存区: php_buffer缓存区

?
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
  
php提前响应请求继续执行代码(伪异步)
 
 
#有时候,我们都可能需要先让php给浏览器输出,然后在后台慢慢处理其他不用输出耗时的业务.
#php如何实现这个功能?
 
#1. ignore_user_abort(true);
这个函数可以忽略客户端的断开,继续执行php代码,直到异常终止(受30秒超时终止限制)
 
 
#2. set_time_limit(0);
在php常规web模式下,默认有个执行超时时间(30秒),当执行到30秒时,会直接终止该php进程,
可使用set_time_limit(0),设置为用不超时.
 
#上面两个函数配置使用,客户端就算断开,就算超过30秒,php进程也会一直执行下去,直到执行完成
 
 
#3. 实时输出到 Nginx | Apache (php_buffer缓存区)
//------------------------------------- demo    begin
//apache方法,需要关闭apache缓冲区
for($i=0;$i<1000;$i++){
    echo $i;
 
    ob_flush();//刷新PHP自身缓冲区
 
    flush();//刷新(特指apache)web服务器的缓冲区,输出数据
 
    sleep(1);
}
 
//nginx缓冲区
ob_end_clean();
ob_implicit_flush();
header('X-Accel-Buffering: no'); // 关键是加了这一行。
for($i=0;$i<1000;$i++){
    echo $i;
    sleep(1);
}
//------------------------------------- demo    end
 
 
#4. 伪结束响应
# 掌握上面几点,我们即可开始实现这个功能了
#伪结束响应原理是:
#先让php提前输出"已结束响应"代码(其实还没有结束,还可以继续echo输出)
#然后让用户自行关闭窗口,通过set_time_limit和ignore_user_abort函数实现php代码还在后台运行,如以下
//-------------------------------------demo     begin
//apache服务器
set_time_limit(0);
ignore_user_abort(true);
//巴拉巴拉这里处理了一些事情
echo "完成请求,3秒自动关闭页面(一段js自动关闭页面)";
ob_flush();//刷新PHP自身缓冲区
flush();//刷新(特指apache)web服务器的缓冲区,输出数据
//这里还在巴拉巴拉处理事情\
$i=0;
while(1){
//注意,死循环非常危险,会造成该web进程一直在处理,不会退出,永久占用一个进程,而且管理该进程非常麻烦,建议加个判断啥的
    file_put_contents('test.txt',$i);
    $i++;
    sleep(1);
}
 
//nginx服务器
set_time_limit(0);
ignore_user_abort(true);
//巴拉巴拉这里处理了一些事情
ob_end_clean();
ob_implicit_flush();
header('X-Accel-Buffering: no'); // 关键是加了这一行。
echo "完成请求,3秒自动关闭页面(一段js自动关闭页面)";
//这里还在巴拉巴拉处理事情\
$i=0;
while($i<100){
    //注意,死循环非常危险,会造成该web进程一直在处理,不会退出,永久占用一个进程,而且管理该进程非常麻烦,建议加个判断啥的
    file_put_contents('test.txt',$i);
    $i++;
    sleep(1);
}
//-------------------------------------demo     end
 
 
#5. 提前结束响应
 
#1). 在php-fpm中,有个函数fastcgi_finish_request可使得web服务器提前中断http响应:
//-------------------------------------demo     begin
//php-fpm模式下
set_time_limit(0);
ignore_user_abort(true);
//巴拉巴拉这里处理了一些事情
echo "完成请求,3秒自动关闭页面(一段js自动关闭页面)";
fastcgi_finish_request();//真正的结束响应,后面的echo将不起作用
 
//这里还在巴拉巴拉处理事情
$i=0;
while($i<100){
    //注意,死循环非常危险,会造成该web进程一直在处理,不会退出,永久占用一个进程,而且管理该进程非常麻烦,建议加个判断啥的
    file_put_contents('test.txt',$i);
    $i++;
    sleep(1);
}
//-------------------------------------demo     end
 
# 2). 在非fpm模式下,提前中断
//-------------------------------------demo     begin
//非php-fpm  一般是apache
set_time_limit(0);
ignore_user_abort(true);
ob_end_flush();
ob_start();
//巴拉巴拉这里处理了一些事情
echo '完成请求,3秒自动关闭页面(一段js自动关闭页面)';
header("Content-Type: text/html;charset=utf-8");
header("Connection: close");//告诉浏览器不需要保持长连接
header('Content-Length: '. ob_get_length());//告诉浏览器本次响应的数据大小只有上面的echo那么多
ob_flush();
flush();
//header不会经过buffer,直接输出到浏览器,浏览器接收到之后,直接主动关闭连接
 
//这里还在巴拉巴拉处理事情
$i=0;
while($i<100){
    //注意,死循环非常危险,会造成该web进程一直在处理,不会退出,永久占用一个进程,而且管理该进程非常麻烦,建议加个判断啥的
    file_put_contents('test.txt',$i);
    $i++;
    sleep(1);
}
//-------------------------------------demo     end
 
  


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

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

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

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