我正在运行 Apache 2.4.6(Amazon)和 PHP 5.4.21 的标准安装,并使用以下配置作为我的虚拟主机:
DirectoryIndex index.php
# ...
FallbackResource /index.php
我的index.php
是简单的缩影:
<?php echo "Hello world";
访问时http://<server-name>/
,五秒钟后才显示完整页面,这太神奇了!其他页面的响应时间都符合预期(很快)。
我发现,这五秒钟与该Keep-Alive
功能的默认等待时间有关;在这种情况下,直到 Apache 在等待时间之后切断连接,才会发送分块响应的最后几个字节。顺便说一句,这也完全破坏了持久连接本来可以给你带来的所有好处。
这是 Apache 的一个已知错误吗?还是我忽略了某些非常明显的东西?
答案1
2017/04/18:此问题已在 Apache 2.4.25 中修复:https://bz.apache.org/bugzilla/show_bug.cgi?id=58292
来自错误摘要的解释:
如果在子请求上执行 FallBackResource,服务器将永远不会发送最后一块,从而导致某些客户端出现挂起。
发生这种情况的原因是 EOS 存储桶被子请求过滤器剥离,如果多个子请求过滤器最终出现在一个列表中,则无法正确删除该存储桶
这种行为仅在应用压缩时才会显现,因为这依赖于知道流何时结束;并且 5s 是使用的默认套接字超时。
旧答案
从此错误报告我意识到这个问题可能与该DirectoryIndex
指令有关。
标准 Apache 安装的配置中包含以下部分:
<IfModule dir_module>
DirectoryIndex index.html
</IfModule>
此语句之后的任何指令(例如虚拟主机中的指令)都不会覆盖此设置;相反,它会被添加到请求索引时将尝试的页面堆栈中。在读取请求后立即执行strace httpd -X
并检查调用时,可以确认此行为,例如:stat()
stat("/path/to/vhost/index.html", 0x7fff9dc41b90) = -1 ENOENT
stat("/path/to/vhost/index.php", {st_mode=S_IFREG|0664, st_size=130, ...}) = 0
虽然我不能确切地说出原因,但DirectoryIndex
在指定之前必须清除所有先前的指令DirectoryIndex index.php
,即index.php
必须是尝试处理请求的第一个页面。
可以使用以下配置来完成:
DirectoryIndex disabled
DirectoryIndex index.php