mod_fcgid 用户注意事项(请自行承担使用风险)。
快速解决方案
Joeri Sebrechts 接受的答案确实是有效的。但是,如果您使用 mod_fcgid,您可能会发现此解决方案无法单独运行。换句话说,当调用 flush 函数时,与客户端的连接不会关闭。
mod_fcgid 的FcgidOutputBufferSize 配置参数可能是罪魁祸首。我在以下位置找到了这个提示:
-
this reply of Travers Carter 和
-
this blog post of Seumas Mackinnon。
阅读以上内容后,您可能会得出一个快速解决方案是添加该行的结论(请参阅末尾的“示例虚拟主机”):
FcgidOutputBufferSize 0
在您的 Apache 配置文件(例如,httpd.conf)、您的 FCGI 配置文件(例如,fcgid.conf)或您的虚拟主机文件(例如,httpd-vhosts.conf)中。
在上面的(1)中,提到了一个名为“OutputBufferSize”的变量。这是(2)中提到的FcgidOutputBufferSize的旧名称(见upgrade notes in the Apache web page for mod_fcgid)。
详细信息和第二个解决方案
上述解决方案禁用 mod_fcgid 对整个服务器或特定虚拟主机执行的缓冲。这可能会导致您的网站性能下降。另一方面,情况可能并非如此,因为 PHP 自己执行缓冲。
如果您不想禁用 mod_fcgid 的缓冲,还有另一种解决方案...您可以强制刷新此缓冲区。
下面的代码正是基于 Joeri Sebrechts 提出的解决方案来实现的:
<?php
ob_end_clean();
header("Connection: close");
ignore_user_abort(true); // just to be safe
ob_start();
echo('Text the user will see');
echo(str_repeat(' ', 65537)); // [+] Line added: Fill up mod_fcgi's buffer.
$size = ob_get_length();
header("Content-Length: $size");
ob_end_flush(); // Strange behaviour, will not work
flush(); // Unless both are called !
// Do processing here
sleep(30);
echo('Text user will never see');
?>
添加的代码行本质上是填充 mod_fcgi 的缓冲区,从而强制它刷新。选择数字“65537”是因为FcgidOutputBufferSize 变量的默认值为“65536”,如Apache web page for the corresponding directive 中所述。因此,如果您的环境中设置了另一个值,您可能需要相应地调整此值。
我的环境
- WampServer 2.5
- Apache 2.4.9
- PHP 5.5.19 VC11,x86,非线程安全
- mod_fcgid/2.3.9
- Windows 7 专业版 x64
示例虚拟主机
<VirtualHost *:80>
DocumentRoot "d:/wamp/www/example"
ServerName example.local
FcgidOutputBufferSize 0
<Directory "d:/wamp/www/example">
Require all granted
</Directory>
</VirtualHost>