Fork me on GitHub

排队也要讲效率:HTTP的连接管理

前面有说到HTTP的性能,七个字概括:“不算差,不够好”,还了解到有“队头阻塞”这一说法,这节学习的重点就是围绕“队头阻塞'这一说法来进行。

一、短连接

HTTP传输数据基于 TCP/IP,每次发送请求前需要先与服务器建立连接,收到响应报文后会立即关闭连接。客户端与服务器的整个连接过程很短暂,不会与服务器保持长时间的连接状态,所以就被称为“短连接”(short-lived connections)。早期的 HTTP 协议也被称为是“无连接”的协议。这就造成一个情况,一次HTTP请求要建立三次握手,那么这一次HTTP请求TCP/IP分别要建立三次连接,就十分的耗时间,如果不好理解的话我们举一个上班打卡的例子学习。

公司里有一个有盖的打卡机器,而且打开盖子十分的麻烦,这样一来,大家排队进行打卡的时候如果打卡需要3秒钟,那么打开盖子就要花一分钟,这样,大家打卡的效率就十分的低,打卡的盖子就和TCP/IP连接建立,需要的时间十分的多,特别的耗费时间。

 

 

 二、长连接

针对短连接暴露出的缺点,HTTP 协议就提出了“长连接”的通信方式,也叫“持久连接”(persistent connections)、“连接保活”(keep alive)、“连接复用”(connection reuse)。

其实解决办法也很简单,用的就是“成本均摊”的思路,既然 TCP 的连接和关闭非常耗时间,那么就把这个时间成本由原来的一个“请求 - 应答”均摊到多个“请求 - 应答”上。

这样虽然不能改善 TCP 的连接效率,但基于“分母效应”,每个“请求 - 应答”的无效时间就会降低不少,整体传输效率也就提高了。

这里看一下短连接与长连接的对比示意图。

 

 

在短连接里发送了三次 HTTP“请求 - 应答”,每次都会浪费 60% 的 RTT 时间。而在长连接的情况下,同样发送三次请求,因为只在第一次时建立连接,在最后一次时关闭连接,所以浪费率就是“3÷9≈33%”,降低了差不多一半的时间损耗。显然,如果在这个长连接上发送的请求越多,分母就越大,利用率也就越高。

继续用刚才的打卡机的比喻,公司也觉得这种反复“开盖 - 打卡 - 关盖”的操作太“反人类”了,于是颁布了新规定,早上打开盖子后就不用关上了,可以自由打卡,到下班后再关上盖子。

这样打卡的效率(即服务能力)就大幅度提升了,原来一次打卡需要五六秒钟,现在只要一秒就可以了,上下班时排长队的景象一去不返,大家都开心。

请求头里明确地要求使用长连接机制,使用的字段是Connection,值是“keep-alive”。

不过不管客户端是否显式要求长连接,如果服务器支持长连接,它总会在响应报文里放一个“Connection: keep-alive”字段,告诉客户端:“我是支持长连接的,接下来就用这个 TCP 一直收发数据吧”。

访问一个页面,看响应头和请求头,都是支持长连接的。

 

 

 三、队头阻塞

“队头阻塞”与短连接和长连接无关,而是由 HTTP 基本的“请求 - 应答”模型所导致的。

 因为 HTTP 规定报文必须是“一发一收”,这就形成了一个先进先出的“串行”队列。队列里的请求没有轻重缓急的优先级,只有入队的先后顺序,排在最前面的请求被最优先处理。如果队首的请求因为处理的太慢耽误了时间,那么队列里后面的所有请求也不得不跟着一起等待,结果就是其他的请求承担了不应有的时间成本。

 

 

 还是用打卡机做个比喻。

上班的时间点上,大家都在排队打卡,可这个时候偏偏最前面的那个人遇到了打卡机故障,怎么也不能打卡成功,急得满头大汗。等找人把打卡机修好,后面排队的所有人全迟到了。

性能优化:

以打卡为例,公司里可以再多买几台打卡机放在前台,这样大家可以不用挤在一个队伍里,分散打卡,一个队伍偶尔阻塞也不要紧,可以改换到其他不阻塞的队伍。

这在 HTTP 里就是“并发连接”(concurrent connections),也就是同时对一个域名发起多个长连接,用数量来解决质量的问题。

但这种方式也存在缺陷。如果每个客户端都想自己快,建立很多个连接,用户数×并发数就会是个天文数字。服务器的资源根本就扛不住,或者被服务器认为是恶意攻击,反而会造成“拒绝服务”。

所以,HTTP 协议建议客户端使用并发,但不能“滥用”并发。RFC2616 里明确限制每个客户端最多并发 2 个连接。不过实践证明这个数字实在是太小了,众多浏览器都“无视”标准,把这个上限提高到了 6~8。后来修订的 RFC7230 也就“顺水推舟”,取消了这个“2”的限制。

但“并发连接”所压榨出的性能也跟不上高速发展的互联网无止境的需求,还有什么别的办法吗?

公司发展的太快了,员工越来越多,上下班打卡成了迫在眉睫的大问题。前台空间有限,放不下更多的打卡机了,怎么办?那就多开几个打卡的地方,每个楼层、办公区的入口也放上三四台打卡机,把人进一步分流,不要都往前台挤。

这个就是“域名分片”(domain sharding)技术,还是用数量来解决质量的思路。

HTTP 协议和浏览器不是限制并发连接数量吗?好,那我就多开几个域名,比如 shard1.chrono.com、shard2.chrono.com,而这些域名都指向同一台服务器 www.chrono.com,这样实际长连接的数量就又上去了,真是“美滋滋”。不过实在是有点“上有政策,下有对策”的味道。

四、课后作业

1. 在开发基于 HTTP 协议的客户端时应该如何选择使用的连接模式呢?短连接还是长连接?

答:一般使用长连接,除非明确知道只会发送一个请求,比如游戏内连接兑换码服务进行礼包兑换。
(1)服务器端设置keepalive_timeout表示多长时间没有数据则关闭连接。
(2)服务器端设置keepalive_requests,表示该连接上处理多少个请求后关闭连接。
(3)服务器端设置最大连接数,当连接达到上限之后拒绝连接,也可以采用限流措施等。
2. 应当如何降低长连接对服务器的负面影响呢?

答:长连接会长期占用服务器资源,根据服务器性能设置连接数和长连接超时时间,保证服务器在承受足够负担的情况下工作最高的效率。

至此,结束。

posted @ 2021-02-24 11:16  叶语婷  阅读(242)  评论(0编辑  收藏  举报