共计 7343 个字符,预计需要花费 19 分钟才能阅读完成。
本文内容和编写思路是基于邓昀泽的“大规模并发 IM 服务架构设计”、“IM 的弱网场景优化”两文的提纲进行的,感激邓昀泽的自私分享。
1、引言
接上篇《一套亿级用户的 IM 架构技术干货 (上篇):整体架构、服务拆分等》,本文次要聚焦这套亿级用户的 IM 架构的一些比拟细节但很重要的热门问题上,比方:音讯可靠性、音讯有序性、数据安全性、挪动端弱网问题等。
以上这些热门 IM 问题每个话题其实都能够独自成文,但限于文章篇幅,本文不会一一问题具体深刻地探讨,次要以抛砖引玉的形式疏导阅读者了解问题的要害,并针对问题提供专项钻研文章链接,不便有选择性的深刻学习。心愿本文能给你的 IM 开发带来一些好处。
本文已同步公布于“即时通讯技术圈”公众号,欢送关注 。公众号上的链接是:点此进入。
2、系列文章
为了更好以进行内容出现,本文拆分两了高低两篇。
本文是 2 篇文章中的第 2 篇:
《一套亿级用户的 IM 架构技术干货 (上篇):整体架构、服务拆分等》
《一套亿级用户的 IM 架构技术干货 (下篇):可靠性、有序性、弱网优化等》(本文)
本篇次要聚焦这套亿级用户的 IM 架构的一些比拟细节但很重要的热门问题上。
3、音讯可靠性问题
音讯的可靠性是 IM 零碎的典型技术指标,对于用户来说,音讯能不能被牢靠送达(不丢音讯),是应用这套 IM 的信赖前提。
换句话说,如果这套 IM 零碎不能保障不丢音讯,那相当于发送的每一条音讯都有被失落的概率,对于用户而言,肯定会不会“释怀”地应用它,即“不信赖”这套 IM。
从产品经理的角度来说,有这样的技术阻碍存在,再怎么费劲的推广,最终用户都会很快散失。所以一套 IM 如果不能保障音讯的可靠性,那问题是很重大的。
PS: 如果你对 IM 音讯可靠性的问题还没有一个直观的映象的话,通过《零根底 IM 开发入门 (三):什么是 IM 零碎的可靠性?》这篇文章能够通俗易懂的了解它。
如上图所示,音讯可靠性次要依赖 2 个逻辑来保障:
- 1)上行音讯可靠性;
- 2)上行音讯可靠性。
1)针对上行音讯的可靠性,能够这样的思路来解决:
用户发送一个音讯(假如协定叫 PIMSendReq),用户要给这个音讯设定一个本地 ID,而后期待服务器操作实现给发送者一个 PIMSendAck(本地 ID 统一),通知用户发送胜利了。
如果期待一段时间,没收到这个 ACK,阐明用户发送不胜利,客户端 SDK 要做重试操作。
2)针对上行音讯的可靠性,能够这样的思路来解决:
服务收到了用户 A 的音讯,要把这个音讯推送给 B、C、D 3 集体。假如 B 长期掉线了,那么在线推送很可能会失败。
因而确保上行可靠性的外围是: 在做推送前要把这个推送申请缓存起来。
这个缓存由存储系统来保障,MsgWriter 要保护一个(离线音讯列表),用户的一条音讯,要同时写入 B、C、D 的离线音讯列表,B、C、D 收到这个音讯当前,要给存储系统一个 ACK,而后存储系统把音讯 ID 从离线音讯列表里拿掉。
针对音讯的可靠性问题,具体的解决思路还能够从另一个维度来思考:即实时音讯的可靠性和离线音讯的可靠性。
有趣味能够深刻读一读这两篇:
《IM 音讯送达保障机制实现 (一):保障在线实时音讯的牢靠投递》
《IM 音讯送达保障机制实现 (二):保障离线音讯的牢靠投递》
而对于离线音讯的可靠性来说,单聊和群聊又有很大区别,无关群聊的离线音讯牢靠投递问题,能够深刻读一读《IM 开发干货分享:如何优雅的实现大量离线音讯的牢靠投递》。
4、音讯有序性问题
音讯的有序性问题是分布式 IM 零碎中的另一个技术“硬骨头”。
因为是分布式系统,客户端和服务器的时钟可能是不同步的。如果简略依赖某一方的时钟,就会呈现大量的音讯乱序。
比方只依赖客户端的时钟,A 比 B 工夫晚 30 分钟。所有 A 给 B 发消息,而后 B 给 A 回复。
发送程序是:
客户端 A:“XXX”
客户端 B:“YYY”
接管方的排序就会变成:
客户端 B:“YYY”
客户端 A:“XXX”
因为 A 的工夫晚30分钟,所有 A 的音讯都会排在前面。
如果只依赖服务器的时钟,也会呈现相似的问题,因为 2 个服务器工夫可能也不统一。尽管客户端 A 和客户端 B 时钟统一,然而 A 的音讯由服务器 S1 解决,B 的音讯由服务器 S2 解决,也会导致同样音讯乱序。
为了解决这种问题,我的思路是通过能够做这样一系列的操作来实现。
1)服务器工夫对齐:
这部分就是后端运维的锅了,由系统管理员来尽量保障,没有别的招儿。
2)客户端通过工夫调校对齐服务器工夫:
比方:客户端登录当前,拿客户端工夫和服务器工夫做差值计算,发送音讯的时候思考这部分差值。
在我的 im 架构里,这个能把工夫对齐到 100ms 这个级,差值再小的话就很艰难了,因为协定在客户端和服务器之间传递速度 RTT 也是不稳固的(网络传输存在不可控的提早危险嘛)。
3)音讯同时带上本地工夫和服务器工夫:
具体能够这样的解决:排序的时候,对于同一个人的音讯,依照音讯本地工夫来排;对于不同人的音讯,依照服务器工夫来排,这是插值排序算法。
PS: 对于音讯有序性的问题,显然也不是下面这三两句话能讲的分明,如果你想更艰深一了解它,能够读一读《零根底 IM 开发入门 (四):什么是 IM 零碎的音讯时序一致性?》。
另外: 从技术实际可行性的角度来说,《一个低成本确保 IM 音讯时序的办法探讨》、《如何保障 IM 实时音讯的“时序性”与“一致性”?》这两篇中的思路能够借鉴一下。
实际上,音讯的排序问题,还能够从音讯 ID 的角度去解决(也就是通过算法让音讯 ID 产生程序性,从而依据音讯 ID 就能达到音讯排序的目标)。
无关程序的音讯 ID 算法问题,这两篇十分值得借鉴:《IM 音讯 ID 技术专题 (一):微信的海量 IM 聊天音讯序列号生成实际(算法原理篇)》、《IM 音讯 ID 技术专题 (三):解密融云 IM 产品的聊天音讯 ID 生成策略》,我就不废话了。
5、音讯已读同步问题
音讯的已读未读性能,如下图所示:
上图就是钉钉中的已读未读音讯。这在企业 IM 场景下十分有用(因为做领导的都喜爱,你懂的)。
已读未读性能,对于一对一的单聊音讯来说,还比拟好了解:就是多加一条对应的回执息(当用户浏览这条音讯时发回)。
但对于群聊这说,这一条音讯有多少人已读、多少人未读,想实现这个成果,那就真的有点麻烦了。对于群聊的已读未读性能实现逻辑,这里就不开展了,有趣味能够读一下这篇《IM 群聊音讯的已读回执性能该怎么实现?》。
回归到本节的主题“已读同步”的问题,这显示难度又进一级,因为已读未读回执不只是针对“账号”,当初还要细分到“同一账号在不同端登陆”的状况,对于已读回执的同步逻辑来说,这就有点复杂化了。
在这里,依据我这边 IM 架构的实践经验,提供一些思路。
具体来说就是: 用户可能有多个设施登录同一个账户(比方:Web PC 和挪动端同时登陆),这种状况下的已读未读性能,就须要来实现已读同步,否则在设施 1 看过的音讯,设施 2 看到仍然是未读音讯,从产品的角度来说,这就影响用户体验了。
对于我的 im 架构来说,已读同步次要依赖 2 个逻辑来保障:
- 1)同步状态保护,为用户的每一个 Session,保护一个工夫戳,保留最初的读音讯工夫;
- 2)如果用户关上了某个 Session,且用户有多个设施在线,发送一条 PIMSyncRead 音讯,告诉其它设施。
6、数据安全问题
6.1 根底
IM 零碎架构中的数据安全比个别零碎要简单一些,从通信的角度来说,它波及到 socket 长连贯通信的安全性和 http 短连贯的两重安全性。而随着 IM 在挪动端的风行,又要在安全性、性能、数据流量、用户体验这几个维度上做衡量,所以想要实现一套欠缺的 IM 平安架构,要面临的挑战是很多的。
IM 零碎架构中,所谓的数据安全,次要是通信安全和内容平安。
6.2 通信安全
所谓的通信安全,这就要了解 IM 通信的服务组成。
目前来说,一个典型的 im 零碎,次要由两种通信服务组成:
- 1)socket 长连贯服务:技术上也就是少数人耳熟能详的网络通信这一块,再细化一点也就是 tcp、udp 协定这一块;
- 2)http 短连贯服务:也就是最罕用的 http rest 接口那些。
对于晋升长连贯的安全性思路,能够深刻浏览《通俗易懂:一篇把握即时通讯的音讯传输平安原理》。另外,微信团队分享的《微信新一代通信安全解决方案:基于 TLS1.3 的 MMTLS 详解》一文,也十分有参考意义。
如果是通信安全级别更高的场景,能够参考《即时通讯平安篇(二):探讨组合加密算法在 IM 中的利用》,文中对于组合加密算法的应用思路十分不错。
至于短连贯安全性,大家就很相熟了,开启 https 少数状况下就够用了。如果对于 https 不甚了解,能够从这几篇开始:《一文读懂 Https 的安全性原理、数字证书、单项认证、双项认证等》、《即时通讯平安篇(七):如果这样来了解 HTTPS,一篇就够了》。
6.3 内容平安
这个可能不太好了解,下面既然实现了通信安全,那为什么还要纠结“内容平安”?
咱们理解一下所谓的密码学三大作用:加密(Encryption)、认证(Authentication),鉴定(Identification)。
具体来说就是:
加密:避免好人获取你的数据。
认证:避免好人批改了你的数据而你却并没有发现。
鉴权:避免好人混充你的身份。
在上节中,歹意攻击者如果在通信环节绕开或冲破了“鉴权”、“认证”,那么依赖于“鉴权”、“认证”的“加密”,实际上也有可有被破解。
针对上述问题,那么咱们须要对内容进行更加平安独立的加密解决,就这是所谓的“端到端加密”(E2E)。
比方,那个号称无奈被破解的 IM——Telegram,实际上就是应用了端到端加密技术。
对于端到端加密,这里就不深入探讨,这里有两篇文章有趣味地能够深刻浏览:
《挪动端平安通信的利器——端到端加密(E2EE)技术详解》
《简述实时音视频聊天中端到端加密(E2EE)的工作原理》
7、雪崩效应问题
在分布式的 IM 架构中,存在雪崩效应问题。
咱们晓得,分布式的 IM 架构中,为了高可用性,用户每次登陆都是依据负载平衡算法调配到不同的服务器。那么问题就来了。
举个例子: 假如有 5 个机房,其中 A 机房故障,导致这个机房先前服务的用户都跑去 B 机房。B 机房不堪重负也解体了,A+ B 的用户跑去机房 C,连锁反应会导致所有服务挂掉。
避免雪崩效应须要在服务器架构,客户端链接策略上有一些配合的解决方案。服务器须要无限流能力作为根底,次要是限度总服务用户数和短时间链接用户数。
在客户端层面,发现服务断开之后要有一个策略,避免大量用户同一时间去链接某个服务器。
通常有 2 种计划:
- 1)退却:重连之间设置一个随机的距离;
- 2)LBS:跟服务器申请重连的新的服务器 IP,而后由 LBS 服务去升高短时间调配到同一个服务器的用户量。
这 2 种计划互不抵触,能够同时做。
8、弱网问题
8.1 弱网问题的起因
鉴于现在 IM 在挪动端的风行,弱网是很常态的问题。电梯、火车上、开车、地铁等等场景,都会遇到显著的弱网问题。
那么为什么会呈现弱网问题?
要答复这个问题,那就须要从无线通信的原理下来寻找答案。
因为无线通信的品质受制于很多方面的因素,比方:无线信号强弱变动快、信号烦扰、通信基站散布不均、挪动速度太快等等。要说分明这个问题,那就真是三天三夜都讲不完。
有趣味的读者,肯定要仔细阅读上面这几篇文章,相似的跨学科科谱式文章并不多见:
《IM 开发者的零根底通信技术入门 (十一):为什么 WiFi 信号差?一文即懂!》
《IM 开发者的零根底通信技术入门 (十二):上网卡顿?网络掉线?一文即懂!》
《IM 开发者的零根底通信技术入门 (十三):为什么手机信号差?一文即懂!》
《IM 开发者的零根底通信技术入门 (十四):高铁上无线上网有多难?一文即懂!》
弱网问题是挪动端 APP 的必修课,上面这几篇总结也值得借鉴:
《挪动端 IM 开发者必读 (一):通俗易懂,了解挪动网络的“弱”和“慢”》
《挪动端 IM 开发者必读 (二):史上最全挪动弱网络优化办法总结》
《古代挪动端网络短连贯的优化伎俩总结:申请速度、弱网适应、平安保障》
《百度 APP 挪动端网络深度优化实际分享 (三):挪动端弱网优化篇》
8.2 IM 针对弱网问题的解决
对于 IM 来说,弱网问题并不是很简单,外围是做好音讯的重发、排序以及接收端的重试。
为了解决好弱网引发的 IM 问题,通常能够通过以下伎俩改善:
- 1)音讯主动重发;
- 2)离线音讯接管;
- 3)重发消息排序;
- 4)离线指令解决。
上面将逐个展开讨论。
8.3 音讯主动重发
坐地铁的时候,常常遇到列车开起来当前,网络断开,发送音讯失败。
这时候产品有 2 种表现形式:
- a、间接通知用户发送失败;
- b、放弃发送状态,主动重试 3 - 5 次(3 分钟)当前通知用户发送失败。
显然: 主动重试失败当前再通知用户发送失败体验要好很多。尤其是在网络闪断状况下,重试成功率很高,很可能用户基本感知不到有发送失败。
从技术上: 客户端 IMSDK 要把每条音讯的状态监控起来。发送音讯不能简略的调用一下网络发送申请,而是要有一个状态机,治理几个状态:初始状态,发送中,发送失败,发送超时。对于失败和超时的状态,要启用重试机制。
这里还有一篇对于重试机制设计的探讨帖子,有趣味能够看看:《齐全自已开发的 IM 该如何设计“失败重试”机制?》。
《IM 音讯送达保障机制实现 (一):保障在线实时音讯的牢靠投递》一文中对于音讯超时与重传机制的实现思路,也能够参考一下。
8.4 离线音讯接管
古代 IM 是没有“在线”这个状态的,不须要给用户这个信息。然而从技术的层面,用户掉线了还是要正确的去感知的。
感知办法有几条:
- a、信令长连贯状态:如果长时间没收到到服务器的心跳反馈,阐明掉线了;
- b、网络申请失败次数:如果屡次网络申请失败,阐明”可能“掉线了;
- c、设施网络状态检测:间接检测网卡状态就好,个别 Android/iOS/Windows/Mac 都有相应零碎 API。
正确检测到网络状态当前,发现网络从”断开到复原“的切换,要去被动拉取离线阶段的音讯,就能够做到弱网状态不丢音讯(从服务器的离线音讯列表拉取)。
下面文字中提到的网络状态的确定,波及到 IM 里网络连接检查和保活机制问题,是 IM 里比拟头疼的问题。
一不小心,又踩进了 IM 网络保活这个坑,我就不在这里开展,有趣味肯定要读读上面的文章:
《为何基于 TCP 协定的挪动端 IM 依然须要心跳保活机制?》
《一文读懂即时通讯利用中的网络心跳包机制:作用、原理、实现思路等》
《微信团队原创分享:Android 版微信后盾保活实战分享 (网络保活篇)》
《挪动端 IM 实际:实现 Android 版微信的智能心跳机制》
《挪动端 IM 实际:WhatsApp、Line、微信的心跳策略剖析》
8.5 重发消息排序
弱网逻辑的另一个坑是音讯排序。
如果有 A、B、C 3 条音讯,A、C 发送胜利,B 发送的时候遇到了网络闪断,B 触发主动重试。
那么接管方的接管程序应该是 A B C 还是 A C B 呢?我察看过不同的 IM 产品,解决逻辑各不相同,这个大家有趣味能够去玩一下。
这个解决办法是要依赖上一篇服务架构里提到的差值排序,同一个人收回的音讯,排序按音讯附带的本地工夫来排。不同人的音讯,依照服务器工夫排序。
具体我这边就不再得复,能够回头看看本篇中的第四节“4、音讯有序性问题”。
8.6 离线指令解决
局部指令操作的时候,网络可能呈现了问题,等网络复原当前,要主动同步给服务器。
举一个例子,大家能够试试手机设置为航行模式,而后在微信里删除一个联系人,看看能不能删除。而后从新关上网络,看看这个数据会不会同步到服务器。
相似的逻辑也实用于已读同步等场景,离线状态看过的信息,要正确的跟服务器同步。
8.7 小结一下
IM 的弱网解决,其实绝对还是比较简单的,基本上主动重试 + 音讯状态就能够解决绝大部分的问题了。
一些细节解决也并不简单,次要起因是 IM 的音讯量比拟小,网络复原后能疾速的复原操作。
视频会议在弱网下的逻辑,就要简单的多了。尤其是高丢包的弱网环境下,要尽力去保障音视频的流畅性。
9、本文小结
《一套亿级用户的 IM 架构技术干货》这期文章的高低两篇就这么侃完了,上篇波及到的 IM 架构问题倒还好,下篇一不小心又带出了 IM 里的各种热门问题“坑”,搞 IM 开发直是一言难尽。。。
倡议 IM 开发的入门敌人们,如果想要系统地学习挪动端 IM 开发的话,应该去读一读我整顿的那篇 IM 开发“从入门到放弃”的文章(哈哈哈),就是这篇《新手入门一篇就够:从零开发挪动端 IM》。具体我就不再开展了,不然这篇幅又要刹不住车了。。。
10、参考资料
[1] 大规模并发 IM 服务架构设计
[2] IM 的弱网场景优化
[3] 零根底 IM 开发入门 (三):什么是 IM 零碎的可靠性?
[4] IM 音讯送达保障机制实现 (一):保障在线实时音讯的牢靠投递
[5] IM 开发干货分享:如何优雅的实现大量离线音讯的牢靠投递
[6] 即时通讯平安篇(二):探讨组合加密算法在 IM 中的利用
[7] 微信新一代通信安全解决方案:基于 TLS1.3 的 MMTLS 详解
附录:更多 IM 开发文章汇总
《零根底 IM 开发入门 (一):什么是 IM 零碎?》
《零根底 IM 开发入门 (二):什么是 IM 零碎的实时性?》
《IM 开发干货分享:如何优雅的实现大量离线音讯的牢靠投递》
《IM 开发干货分享:有赞挪动端 IM 的组件化 SDK 架构设计实际》
《IM 开发宝典:史上最全,微信各种性能参数和逻辑规定材料汇总》
《IM 开发干货分享:我是如何解决大量离线音讯导致客户端卡顿的》
《从客户端的角度来谈谈挪动端 IM 的音讯可靠性和送达机制》
《腾讯技术分享:社交网络图片的带宽压缩技术演进之路》
《挪动端 IM 中大规模群音讯的推送如何保障效率、实时性?》
《挪动端 IM 开发须要面对的技术问题》
《开发 IM 是本人设计协议用字节流好还是字符流好?》
《请问有人晓得语音留言聊天的支流实现形式吗?》
《IM 单聊和群聊中的在线状态同步应该用“推”还是“拉”?》
《IM 群聊音讯如此简单,如何保障不丢不重?》
《谈谈挪动端 IM 开发中登录申请的优化》
《挪动端 IM 登录时拉取数据如何作到省流量?》
《通俗易懂:基于集群的挪动端 IM 接入层负载平衡计划分享》
《微信对网络影响的技术试验及剖析(论文全文)》本文已同步公布于“即时通讯技术圈”公众号。
▲ 本文在公众号上的链接是:点此进入。同步公布链接是:http://www.52im.net/thread-3445-1-1.html