由于存在这些以及其他类似的问题,而HTTP 1.1标准中也未对此做出说明,HTTP管道技术的应用非常有限,虽然其优点毋庸置疑。今天,一些支持管道的浏览器,通常都将其作为一个高级配置选项,但大多数浏览器都会禁用它。换句话说,如果浏览器是Web应用的主要交付工具,那还是很难指望通过HTTP管道来提升性能。
使用多个TCP连接由于HTTP 1.x不支持多路复用,浏览器可以不假思索地在客户端排队所有HTTP请求,然后通过一个持久连接,一个接一个地发送这些请求。然而,这种方式在实践中太慢。实际上,浏览器开发商没有别的办法,只能允许我们并行打开多个TCP会话。多少个?现实中,大多数现代浏览器,包括桌面和移动浏览器,都支持每个主机打开6个连接。
进一步讨论之前,有必要先想一想同时打开多个TCP连接意味着什么。当然,有正面的也有负面的。下面我们以每个主机打开最多6个独立连接为例:
客户端可以并行分派最多6个请求;
服务器可以并行处理最多6个请求;
第一次往返可以发送的累计分组数量(TCP cwnd)增长为原来的6倍。
在没有管道的情况下,最大的请求数与打开的连接数相同。相应地,TCP拥塞窗口也要乘以打开的连接数量,从而允许客户端绕开由TCP慢启动规定的分组限制。这好像是一个方便的解决方案。我们再看看这样做的代价:
更多的套接字会占用客户端、服务器以及代理的资源,包括内存缓冲区和CPU时钟周期;
并行TCP流之间竞争共享的带宽;
由于处理多个套接字,实现复杂性更高;
即使并行TCP流,应用的并行能力也受限制。
实践中,CPU和内存占用并非微不足道,由此会导致客户端和服务器端的资源占用量上升,运维成本提高。类似地,由于客户端实现的复杂性提高,开发成本也会提高。最后,说到应用的并行性,这种方式提供的好处还是非常有限的。这不是一个长期的方案。了解这些之后,可以说今天之所以使用它,主要有三个原因:
作为绕过应用协议(HTTP)限制的一个权宜之计;
作为绕过TCP中低起始拥塞窗口的一个权宜之计;
作为让客户端绕过不能使用TCP窗口缩放”的一个权宜之计。
后两个针对TCP的问题(窗口缩放和cwnd)最好是通过升级到最新的OS内核来解决。cwnd值最近又提高到了10个分组,而所有最新的平台都能可靠地支持TCP窗口缩放。这当然是好消息。但坏消息是,没有更好办法绕开HTTP 1.x的多路复用问题。
只要必须支持HTTP 1.x客户端,就不得不想办法应对多TCP流的问题。而这又会带来一个明显的问题:为什么浏览器要规定每个主机6个连接呢?恐怕有读者也猜到了,这个数字是多方平衡的结果:这个数字越大,客户端和服务器的资源占用越多,但随之也会带来更高的请求并行能力。每个主机6个连接只不过是大家都觉得比较安全的一个数字。对某些站点而言,这个数字已经足够了,但对其他站点来说,可能还满足不了需求。
域名分区HTTP 1.x协议的一项空白强迫浏览器开发商引入并维护着连接池,每个主机最多6个TCP流。好的一方面是对这些连接的管理工作都由浏览器来处理。作为应用开发者,你根本不必修改自己的应用。不好的一方面呢,就是6个并行的连接对你的应用来说可能仍然不够用。
根据HTTP Archive的统计,目前平均每个页面都包含90多个独立的资源,如果这些资源都来自同一个主机,那么仍然会导致明显的排队等待(如下图所示)。实际上,何必把自己只限制在一个主机上呢?我们不必只通过一个主机(例如)提供所有资源,而是可以手工将所有资源分散到多个子域名:{shard1, shardn}.example.com。由于主机名称不一样了,就可以突破浏览器的连接限制,实现更高的并行能力。域名分区使用得越多,并行能力就越强!