本文在编写时参考了博客作者“鹿呦呦”和在线课程“即时消息技术剖析与实战”的相关资料,一并表示感谢。
1、引言
随着移动互联网络的发展,IM技术的应用已经不仅限于聊天应用本身,它早已融入各种应用形态中,比如:直播中的主播互动、联网游戏中的玩家互动、外卖/打车应用中的实时位置共享、在线教育应用中的互动白板等。
在这些风格迥异的应用场景下,IM技术所呈现出来的功能形态虽有不同,但“实时性”这个技术特征并无区别。
![](https://img2020.cnblogs.com/blog/1834368/202009/1834368-20200918133953429-625627319.jpg)
那么,对于技术门外汉来说,到底什么是IM的“实时性”?该如何理解它?这就是本文想要讨论的主题。
区别于强大的原生应用,Web端的IM系统,在很长一段时间内想实现真正的“实时性”,是非常困难的,因为无法直接使用UDP、TCP通信协议,在HTML5中的WebSocket出现之前,Web端几乎没有真正意义上的“双向实时通信”这种技术存在。
正因为如此,理解Web端即时通信技术的演进,也就自然而然能循序渐进地体会到IM系统中的“实时性”了。所以本文将围绕Web端即时通讯技术,为你展开IM“实时性”这个话题。
友情提示:本系列文章侧重于理论概念的讲述,篇幅有限,点到即止,如需系统、深入、具体地学习IM技术的方方面面,请从此文入手:《新手入门一篇就够:从零开发移动端IM》(史诗级文章,适合从入门到放弃)。
学习交流:
- 即时通讯/推送技术开发交流5群:215477170 [推荐]
- 移动端IM开发入门文章:《新手入门一篇就够:从零开发移动端IM》
- 开源IM框架源码:https://github.com/JackJiang2011/MobileIMSDK
(本文同步发布于:http://www.52im.net/thread-3143-1-1.html)
2、系列文章目录
《IM开发快速入门(二):什么是IM系统的实时性?》(* 本文)
《IM开发快速入门(三):什么是IM系统的可靠性? (稍后发布)》
《IM开发快速入门(四):什么是IM系统的一致性? (稍后发布)》
《IM开发快速入门(五):什么是IM系统的安全性? (稍后发布)》
《IM开发快速入门(六):什么是IM系统的的心跳机制? (稍后发布)》
《IM开发快速入门(七):如何理解并实现IM系统消息未读数? (稍后发布)》
《IM开发快速入门(八):如何理解并实现IM系统的多端消息漫游? (稍后发布)》
3、短轮询技术
在早期的Web时代,技术的创造者们无法预见如今各种选进的技术应用形式,他们认为数据只是用来“看”的,也数据的获取基本就是“请求 -> 响应”这种一问一答形式。包括我们平时浏览的各种门户网站都是采用的“请求响应”模式。
这种依赖于用户“主动”请求的数据获取模式,如果想实现IM系统,是无法即时获得最新的聊天消息的,因为用户并不知道新消息什么时候到来,而服务端也没有办法主动通知用户。
在这个时期,虽然技术和思路都受当时技术水平的限制,但IM总不能不做吧。
于是,一种被称为“短轮询”的数据获取模式出现了。在“短轮询”模式下,IM客户端定时轮询服务端,以便让用户知道是否有新的聊天消息存在。
这种模式下,服务端收到请求后,即刻查询是否存在新消息,有就返回给客户端,没有则返回空并立即关闭连接。
相较于前面用户需要“手动”去刷新页面的方式,这种模式只是将用户的“手动”变为“自动”而已,技术本质并没有发生任何实质性改变。
短轮询这种模式,就好比旧时代一个等待重要邮件的人,他需要每天自已跑到邮局,主动去问是否有自己的信件,有就拿回家,如果没有,则第二天继续去问。一来一去,非常低效。
技术原理总结如下图所示:
短轮询这种模式有好处,也有坏处。
好处是:
- 1)技术简单,容易实现;
- 2)可维护性强,因为它没什么复杂的。
坏处是:
- 1)因为无法预知数据是否存在,所以多数请求是无用的,浪费计算资源;
- 2)为了提升实时性,高频率的请求会加大服务端的性能负载。
总结一下就是,短轮询这种模式对于IM技术大拿来说,显的非常low,因为技术实现实在是简单粗暴。
4、长轮询技术
正如你所见,用短轮询技术来保证IM的实时性,确实难说优雅。不过,这难不倒无所不能的程序员,一种被称为“长轮询”的数据获取模式出现了。
从技术上来说,长轮询实现的IM相较于短轮询最大的改进在于:短轮询情况下,服务端不管有没有新消息,请求结束就会立即断开连接。而长轮询时,如果本次请求没有新消息发生,糨不会马上断开连接并返回,而是会将本次连接“挂起”一段时间,如果在这段“挂起”时间内有新的聊天消息出现,就能马上读取并立即返回给客户端,接着结束本次连接。一段时间后又会再次发起请求,如此周而复始。
长轮询这种模式,拿上节等待邮件的这个例子来说,就好比收信的人每天到邮局去问是否有信件,如果没有,他不马上回家,而是在邮局待上一段时间,如果这段时间过去了,还是没有,就先回家,接着第二天再来。
技术原理总结如下图所示:
![](https://img2020.cnblogs.com/blog/1834368/202009/1834368-20200918134225421-709659193.jpg)
长轮询的优点是:
- 1)相较于短连询,一定程度降低了服务端请求负载;
- 2)相较于短连询,实时性有提升,因为它是主动“等”消息。
长轮询的缺点是:
- 1)长论询模式下,连接“挂起”的这段时间内,服务端需要配合开启单独的消息查询线程,仍然存在无用功;
- 2)相较于短连询模式,在一次长轮询结束、下次轮询发起前的窗口期内,仍然存在“实时性”盲区。
实际上,在Web端即时通讯技术里,长轮询有个专业的术语叫“Comet”,有兴趣可以详细学习《Comet技术详解:基于HTTP长连接的Web端实时通信技术》。
5、轮询无法实现真正的“实时性”
对于Web端即时通讯技术来说,上面提到的无论是短轮询,还是长轮询,它们都存在“实时性”盲区。
我们回到上两节介绍的短轮询和长轮询技术原理图。
先看看短轮询这张图:
![](https://img2020.cnblogs.com/blog/1834368/202009/1834368-20200918134217919-1909264746.jpg)
很明显,短轮询在每次轮询结束和下次轮询开始的间隔期内,是无法感知到新消息的,这也便形成了“实时性盲区”。换句话说,短轮询技术在“实时性盲区”内,无法做到“实时”。
再来看看长轮询:
![](https://img2020.cnblogs.com/blog/1834368/202009/1834368-20200918134234634-95230685.jpg)
跟短轮询道理一样,长轮询在每次轮询结束和下次轮询开始的间隔期,依然会形成“实时性盲区”。
要理解纠结轮询技术的实时性缺陷,就得了解它们背后的技术——HTTP协议了。
HTTP协议设计的目的,就是为了实现“请求--响应”这种模式的数据交互,也就是众所周之的“短连接”设计。而无论是短轮询还是长轮询,都跳不出HTTP的先天技术逻辑(请求--响应--断开)。
所以,归根到底,想要基于HTTP协议来实现IM,要达到真正的“实时性”,是相当勉强的。因为HTTP设计的目的,就是用“短连接”来简化传统TCP长连接通信带来的复杂性,而IM的实时性恰好要用到的又是TCP的长连接特性,所以这就是个悖论。
要真正实现Web端的IM“实时性”,肯定不能强行HTTP上做文章了,我们需要新的技术。
6、WebSocket让Web端IM真正的“实时性”变成可能
好消息是,HTML5中带来了WebSocket技术。WebSocket是真正的全双式双向通信技术(详见:《WebSocket从入门到精通,半小时就够!》)。
下图上旧式轮询技术跟WebSocket的对比图:
![](https://img2020.cnblogs.com/blog/1834368/202009/1834368-20200918134301246-132986007.jpg)
从上图可以看出:
- 1)轮询技术一问一答,在下一个请求发起之前,存在“实时性”盲区;
- 2)WebSocket一旦建立连接后,数据可以随时双向通信(即客户端可以随时向服务端发消息,服务端也可以随时通知客户端有新消息)。
举个例子就是:轮询技术相当于传统的邮件传递方法(你得自已去邮局问有没有新邮件),而WebSocket相当于现代的电话系统,只要你拨通后,随时可以实时收听到对方的声音,对方也能随时收听到你的声音。完美!
总结一下WebSocket 的优点是:
- 1)真正的实时性:支持客户端与服务端真正的双向实时通信;
- 2)大幅降低负载:少了轮询技术中高频率无用的请求,可大大降低服务端QPS压力;
- 3)网络开销降低:一次连接,随时使用,再也不用轮询技术中每次发起HTTP请求(随之而来的是每次HTTP的大量冗余协议头信息等)。
7、本文小结
本文以Web端即时通讯技术的演进为例,从短轮询到长轮询,再到WebSocket,理论联系实际地讲解了Web端IM“实时性”的技术变迁,从而帮助读者理解IM中“实时性”这个最为关键的技术特征。
附录:更多Web端即时通讯资料
《Web端即时通讯技术盘点:短轮询、Comet、Websocket、SSE》
《Comet技术详解:基于HTTP长连接的Web端实时通信技术》
《WebSocket详解(一):初步认识WebSocket技术》
《WebSocket详解(二):技术原理、代码演示和应用案例》
《WebSocket详解(三):深入WebSocket通信协议细节》
《WebSocket详解(四):刨根问底HTTP与WebSocket的关系(上篇)》
《WebSocket详解(五):刨根问底HTTP与WebSocket的关系(下篇)》
《WebSocket详解(六):刨根问底WebSocket与Socket的关系》
《LinkedIn的Web端即时通讯实践:实现单机几十万条长连接》
《Web端即时通讯技术的发展与WebSocket、Socket.io的技术实践》
《Web端即时通讯安全:跨站点WebSocket劫持漏洞详解(含示例代码)》
《开源框架Pomelo实践:搭建Web端高性能分布式IM聊天服务器》
《详解Web端通信方式的演进:从Ajax、JSONP 到 SSE、Websocket》
《MobileIMSDK-Web的网络层框架为何使用的是Socket.io而不是Netty?》
《理论联系实际:从零理解WebSocket的通信原理、协议格式、安全性》
《微信小程序中如何使用WebSocket实现长连接(含完整源码)》
《八问WebSocket协议:为你快速解答WebSocket热门疑问》
《快速了解Electron:新一代基于Web的跨平台桌面技术》
《Web端即时通讯实践干货:如何让你的WebSocket断网重连更快速?》
>> 更多同类文章 ……
本文已同步发布于“即时通讯技术圈”公众号:
▲ 本文在公众号上的链接是:点此进入,原文链接是:http://www.52im.net/thread-3143-1-1.html