一条被「夯住」的专用消息连接,让 90 秒一次的请求也能绝对实时
《即时通讯架构核心技术》第 11 篇:HTTP 长轮询为什么没有延时。
有水友问我说,微博网页端IM通过HTTP收发消息,会不会有延时?
之前做过几十年IM架构,今天和大家聊聊这里面的技术点。
WebIM 一般如何实现消息推送?
通常的有三种实现方式:
1. WebSocket;
2. FlashSocket;
3. HTTP轮询;
其中1和2是基于TCP长连接实现的,水友问的问题,主要是第三类,用HTTP短连接轮询的方式实现消息的收发,能否能保证消息的绝对实时性。
大家为什么会觉得 HTTP 长轮询有延时?
这要从大家理解的“轮询”说起。
什么是轮询?
举个栗子,在火车上想上洗手间,挤到洗手间旁,却发现洗手间有人,于是你只能回座位继续等。过了N分钟,又朝洗手间的方向挤过去,却发现洗手间还是有人,又只能回坐等。这么一而再,再而三的每隔N分钟去洗手间查看洗手间是否有蹲位,这就是轮询。
WEBIM采用上述轮询的方式收发消息会存在什么问题?
可能导致消息延时,某一时刻刚拉取完消息,突然又产生了一条新消息,这条消息就必须等到N分钟之后,下次轮询时,才有机会获取到。延时的最大值是N。
减小轮询时间间隔,是否能解决消息延时的问题?
不能,只能缩小延时,不能保证绝对实时。
同时还会产生更大的问题,大部分的轮询调用,都没有消息返回,造成服务端极大的资源浪费。
不少人基于上述直觉,认为WEBIM使用HTTP长轮询收发消息会有延时。但其实,HTTP长轮询压根不是这回事。
HTTP 长轮询实际是怎么玩的?
专用消息连接。
什么是专用消息链接?
浏览器与web-server之间建立的,一条专门用来接收通知消息的HTTP连接。

专用消息连接的玩法细节如下:
1. 没有消息到达的时候,专用消息连接将被夯住一段时间(例如:90秒);
2. 夯住90秒,专用消息连接被断开之后,立马再发起一个专用消息连接;

3. 在1和2的配合下,每次收到通知消息时,这个连接就能及时将消息带回浏览器页面;

4. 在3的情况下,专用消息连接返回浏览器后,又立刻发起新的专用消息连接,如此一来,浏览器与web-server之间将永远有一条能够接收服务器通知的专用消息连接,以此,来保证WEBIM消息收发的绝对实时性。
总结
1. HTTP长轮询可以保证消息的绝对实时性;
2. 这种实时性不是通过增加轮询频率来保证的;
3. 而是通过专用消息连接,通过夯住HTTP请求来实现的,这个HTTP消息连接对于web-server的请求压力大约是90秒1次,能够大大节省了服务器资源。
检验一下
收消息的问题解决了,那系统通知呢——你以为是推送,其实不一定。第 12 篇,系统通知:推还是拉?
知其然,知其所以然。思路比结论更重要。