TL; DR:Chrome 将此响应标头解释为keep-alive
并在 Firefox 关闭每个连接时保持永久连接。
当我试图优化我的网站的页面加载时间时,我偶然发现了这个问题。
在引用的 RFC 中,我没有找到有关如何Connection
正确处理标头中的多个条目的任何信息。在我看来,实现可以从两种可能性中进行选择:
- 如果有多个条目,您可以选择最适合您需求的条目
- 如果有
close
内部,可以在传输后关闭连接
所以,我需要找出答案。让我们做一些更深入的调查:
我注意到 Chrome 总是发送一个 HTTP/1.1 请求,Connection: keep-alive
而我的 Apache 默认配置总是用一个Connection: close
标头响应。所以我开始调查并使用 Wireshark 查看 TCP 段。
Chrome 必须获取 14 个元素来显示网站,其中大部分是静态的东西,如图像或 css 文件。它完成了 14 个 TCP 连接,并且花费了很多时间(大约 1.2 秒)。在每次请求图像(例如)之后,都会出现一个FIN
标志设置为 1 的 TCP 段。
那么 Chrome 与 Firefox 呢?Chrome 似乎有一个服务器的最大并发连接数为 6。Firefox 具有更精细的配置,并区分持久性(最多 6 个,见 about:config)和非持久性(不同来源的最大数量差异很大)。但是等等...... Chrome 和 Firefox 都发送带有 的 HTTP/1.1 请求标头Connection: keep-alive
,因此两者都应限制为 6(因为这是打开持久连接的请求)。
我决定尝试一个简单的技巧,并将以下几行添加到我.htaccess
的 web 根文件夹中:
<ifModule mod_headers.c>
Header set Connection keep-alive
</ifModule>
服务器现在响应:
Connection: keep-alive, close
现在我再次查看了 TCP 段:现在从 Chrome 到我的服务器只有 9 个连接,并且只有 3 个FIN
标志设置为 1。所以这个技巧似乎奏效了。但是为什么有这3个连接,在数据传输后关闭了连接?X-Powered-By: PHP/5.4.11
正如 HTTP 标头所确认的,这些是 PHP 请求。
那么火狐呢?还有那14个请求!
如何解决这个问题并让 fcgi 进程也与 keep-alive 一起工作?
我在 httpd.conf 配置的虚拟主机部分添加了以下几行:
KeepAlive On
KeepAliveTimeout 5
MaxKeepAliveRequests 100
并删除了添加到.htaccess
. 现在服务器没有发送任何令人困惑的 - Connection: keep-alive, close
,但只有Connection: keep-alive
一切正常!
结论:
连接字段设置为的标头
HTTP/1.1 200 OK
Connection: keep-alive, close
将被 Chrome 解释为keep-alive
Firefox 似乎关闭了每个连接。这似乎取决于实际的实现。
因此,如果您愿意实现一个客户端来处理包含 的响应标头,Connection: keep-alive, close
如果您需要多个请求,我建议您尝试使用 keep-alive。可能发生的最糟糕的事情:服务器将关闭连接,您需要再次连接(这正是您可能拥有的另一个选项!)