0.前言
微信和钉钉是经常会与到两个IM通讯软件,今天从技术角度对他们两个进行分析。这样也方便对于构建IM系统有更好的了解和认识。如果目标是想构建一个IM即时通信的app或者说想了解一下一条消息的收发会经历什么过程可以详细了解一下。
我们可以想想一下微信发送一条消息会经历哪些过程。由此来思考IM系统中需要哪些东西。
目前已经写的IM的文章
分布式websocket即时通信(IM)系统构建指南【第七期】
分布式websocket即时通信(IM)系统保证消息可靠性【第八期】
分布式websocket IM聊天系统相关问题问答【第九期】
什么?websocket也有权限!这个应该怎么做?【第十期】
分布式ID是什么,以美团Leaf为例改造融入自己项目【第十一期】
IM聊天系统为什么需要做消息幂等?如何使用Redis以及Lua脚本做消息幂等【第12期】
哔哩哔哩后续会发视频。大家可以关注的b站账号。
可以直接跳转B站观看视频 点点关注
发送一条消息需要经历什么过程
此时此刻你正在手机屏幕面前给你的好朋友发送消息。然后微信声音一响。您的好友那边就会有一个未读消息。如果您的好友正好在你们两个的聊天页面,那么您的好友会直接收到这个消息。
1.再稍微思考一下,你发送的消息是怎么到达对方手机上的呢。这个需要引入一个服务器的概念。你的消息需要在联网情况下才能发送。然后由服务器中转,然后发送到另一个人手机上了所以会引入服务器
2.那么大家是不是在网络有波动的情况下会遇到消息发送失败的情况呢,为什么会发送失败呢。发送失败是谁的问题呢, 会发送失败在什么地方呢,这些都是技术层面需要考虑的问题。 从产品的角度当消息发送失败的时候无疑对用户体验是不好的。如果一个IM产品发送消息一直失败肯定用户用脚投票就都不使用了
3.发送消息有的时候发送很多的时候会出现感觉发送的消息有乱序的情况,大家应该都遇到过,会不会想过是自己的问题。其实不是,是技术层面的一些问题。
一条简单的消息发送过程中需要尽量解决消息发送失败。解决消息不要乱序等这些过程。消息发送的链路就变的复杂了起来。不管什么IM系统都需要解决这些基本的问题。
简单的来说发送一条消息通常情况下内部都有重试机制 ,就是你点下按钮的那一下后面消息可能发送了好几次。然后会引入一个新的问题。消息重复。通常技术角度在使用一些幂等的策略来实现
上面三个问题其实是IM系统都需要解决的问题。
为了解决上述问题不同应用构建起来自己的消息推送模型,以及解决问题的思路。
企业微信的消息推送模型
企业微信做了哪些事情。
1)实时触达:客户端通过与后台建立长连接,保证消息push的实时触达;
2)及时通知:如果客户端长连接不在,进程被kill了,利用手机厂商的推送平台,推送通知,或者直接拉起进程进行收消息;
3)消息可达:假如遇到消息洪峰,后台的push滞后,客户端有轮询机制进行兜底,保证消息可达;
4)消息防丢:为了防止消息丢失,只要后台逻辑层接收到请求,保证消息写到接收方的存储,失败则重试。如果请求在CGI层就失败,则返回给客户端出消息红点;
5)消息排重:客户端在弱网络的场景下,有可能请求已经成功写入存储,回包超时,导致客户端重试发起相同的消息,那么就造成消息重复。为了避免这种情况发生,每条消息都会生成唯一的appinfo,后台通过建立索引进行排重,相同的消息直接返回成功,保证存储只有一条。
钉钉做了哪些事情
钉钉的消息链路基本上是这样
钉钉IM系统的消息已读链路流程如下:
1)用户对一条消息做读操作后,会发送请求到已读服务;
2)已读服务收到请求后,直接将请求放到消息队列进行异步处理,同时可以达到削峰填谷的目的;
3)已读服务处理完之后,将已读事件推给同步服务,让同步服务将已读事件推送给消息发送者。
钉钉保证消息必达使用了如下策略
如上图所示,发消息流程中,很重要的一步是 receiver 应用做完消息能否发送的校验之后,通过 RocketMQ 将消息投递给 processor做消息入库处理。
投递过程中,将提供三重保险,以保证消息发送万无一失。
第一重保险:receiver 将消息写进 RocketMQ 时, RocketMQ SDK 默认会重试五次(每次尝试不同的 broker ,保障了消息写失败的概率非常小)。
第二重保险:写入 RocketMQ 失败的情况下,会尝试以 RPC 形式将消息投递给 processor
第三重保险:如果 RPC 形式也失败,会尝试将本地 redoLog 通过 Crontab 任务定时将消息回放到 RocketMQ 里面。
文章参考
钉钉参考文章
企业微信参考文章
后续
- 读扩散与写扩散
其实这是一些基本的消息可靠,消息不丢失,不重复,不乱序的一些设计方案。还有需要的地方有消息的读扩散还是写扩散。消息存储这块也是非常需要探讨的。然后微信和企业微信使用的是读扩散。钉钉使用的是写扩散。我自己的IM系统也参考了如上的设计。 - 消息推拉模型
是使用消息推送方式还是消息拉取的方式 - 自己的IM系统也参考了上面的很多设计思想以及在逐步的完善对于IM的知识,有相关的关于IM的问题可以一起讨论