乐趣区

关于im:im即时通讯开发消息模型万人群已读回执消息撤回功能

企业微信作为一款办公协同的产品,聊天音讯收发是最根底的性能。音讯零碎的稳定性、可靠性、安全性尤其重要。

音讯零碎的构建与设计的过程中,面临着较多的难点。而且针对 toB 场景的音讯零碎,须要反对更为简单的业务场景。

针对 toB 场景的特有业务有:

1)音讯鉴权:关系类型有群关系、同企业共事关系、好友关系、团体企业关系、圈子企业关系。收发音讯单方需存在至多一种关系才容许发消息;

2)回执音讯:每条音讯都需记录已读和未读人员列表,波及频繁的状态读写操作;

3)撤回音讯:反对 24 小时的有效期撤回动作;

4)音讯存储:云端存储时间跨度长,最长可反对 180 天音讯存储,数百 TB 用户音讯需优化,缩小机器老本;

5)万人群聊:群人数下限可反对 10000 人,一条群音讯就像一次小型的 DDoS 攻打;

6)微信互通:两个异构的 im 零碎间接买通,可靠性和一致性尤其重要。

整体架构分层如下。

1)接入层:对立入口,接管客户端的申请,依据类型转发到对应的 CGI 层。客户端能够通过长连或者短连连贯 wwproxy。沉闷的客户端,优先用长连贯发动申请,如果长连失败,则选用短连重试。

2)CGI 层:http 服务,接管 wwproxy 的数据包,校验用户的 session 状态,并用后盾派发的秘钥去解包,如解密失败则拒绝请求。解密胜利,则把明文包体转发到后端逻辑层对应的 svr。

3)逻辑层:大量的微服务和异步解决服务,应用自研的 hikit rpc 框架,svr 之间应用 tcp 短连进行通信。进行数据整合和逻辑解决。和内部零碎的通信,通过 http 协定,包含微信互通、手机厂商的推送平台等。

4)存储层:音讯存储是采纳的是基于 levelDB 模型开发 msgkv。SeqSvr 是序列号生成器,保障派发的 seq 枯燥递增不回退,用于音讯的收发协定。

发送方申请后盾,把音讯写入到接管方的存储,而后 push 告诉接管方。接受方收到 push,被动上来后盾收音讯。

不重、不丢、及时触达,这三个是音讯零碎的外围指标:

1)实时触达:客户端通过与后盾建设长连贯,保障音讯 push 的实时触达;

2)及时告诉:如果客户端长连贯不在,过程被 kill 了,利用手机厂商的推送平台,推送告诉,或者间接拉起过程进行收音讯;

3)音讯可达:如果遇到音讯洪峰,后盾的 push 滞后,客户端有轮训机制进行兜底,保障音讯可达;

4)音讯防丢:为了避免音讯失落,只有后盾逻辑层接管到申请,保障音讯写到接管方的存储,失败则重试。如果申请在 CGI 层就失败,则返回给客户端出音讯红点;

5)音讯排重:客户端在弱网络的场景下,有可能申请曾经胜利写入存储,回包超时,导致客户端重试发动雷同的音讯,那么就造成音讯反复。为了防止这种状况产生,每条音讯都会生成惟一的 appinfo,后盾通过建设索引进行排重,雷同的音讯间接返回胜利,保障存储只有一条。

扩散读

即:每条音讯只存一份,群聊成员都读取同一份数据。

长处:节俭存储容量。

毛病:

① 每个用户需存储会话列表,通过会话 id 去拉取会话音讯;

② 收音讯的协定简单,每个会话都须要增量同步音讯,则每个会话都须要保护一个序列号。

扩散写

即:每条音讯存多份,每个群聊成员在本人的存储都有一份。

长处:

① 只须要通过一个序列号就能够增量同步所有音讯,收音讯协定简略;

② 读取速度快,前端体验好;

③ 满足更多 ToB 的业务场景:回执音讯、云端删除。

同一条音讯,在每个人的视角会有不同的体现。例如:回执音讯,发送方能看到已读未读列表,接受方只能看到是否已读的状态。云端删除某条群音讯,在本人的音讯列表隐没,其他人还是可见。

毛病:存储容量的减少。

企业微信采纳了扩散写的形式,音讯收发简略稳固。存储容量的减少,能够通过冷热拆散的计划解决,冷数据存到便宜的 SATA 盘,扩散读体验稍差,协定设计也绝对简单些。

1)每个用户只有一条独立的音讯流。同一条音讯多正本存在于每个用户的音讯流中;

2)每条音讯有一个 seq,在同个用户的音讯流中,seq 是枯燥递增的;

3)客户端保留音讯列表中最大 seq,阐明客户端曾经领有比该 seq 小的所有音讯。若客户端被 push 有新音讯达到,则用该 seq 向后盾申请增量数据,后盾把比此 seq 大的音讯数据返回。

高峰期零碎压力大,偶发的网络稳定或者机器过载,都有可能导致大量的零碎失败。im 系统对及时性要求比拟高,没方法进行削峰解决。那么引入一些柔性的策略,保证系统的稳定性和可用性十分有必要。

具体的做法就是启动过载爱护策略:当 svr 曾经达到最大解决能力的时候,阐明处于一个过载的状态,服务能力会随着负载的增高而急剧下降。如果 svr 过载,则回绝掉局部失常申请,避免机器被压垮,仍然能对外服务。通过统计 svr 的被调耗时状况、worker 应用状况等,断定是否处于过载状态。过载爱护策略在申请顶峰期间起到了爱护零碎的作用,避免雪崩效应。

解决方案思路就是:只管失败,也返回前端胜利,后盾保障最终胜利。

为了保障音讯零碎的可用性,躲避高峰期零碎呈现过载失败导致前端出红点,做了很多优化。

具体策略如下:

1)逻辑层 hold 住失败申请,返回前端胜利,不出红点,后端异步重试,直至胜利;

2)为了避免在零碎呈现大面积故障的时候,重试申请压满队列,只 hold 住半小时的失败申请,半小时后新来的申请则间接返回前端失败;

3)为了防止重试加剧零碎过载,指数时间延迟重试;

4)简单的音讯鉴权(好友关系,企业关系,团体关系,圈子关系),耗时重大,后盾稳定容易造成失败。如果并非明确鉴权不通过,则幂等重试;

5)为了避免作恶申请,限度单个用户和单个企业的申请并发数。例如,单个用户的耗费 worker 数超过 20%,则间接抛弃该用户的申请,不重试。

优化后,后盾的稳定,前端根本没有感知。

零碎稳定性设计 2:零碎解耦

因为产品状态的起因,企业微信的音讯零碎,会依赖很多内部模块,甚至内部零碎。

例如:与微信音讯互通,发送音讯的权限须要放到 ImUnion 去做断定,ImUnion 是一个内部零碎,调用耗时较长。

再如:金融版的音讯审计性能,须要把音讯同步到审计模块,减少 rpc 调用。

再如:客户服务的单聊群聊音讯,须要把音讯同步到 crm 模块,减少 rpc 调用。为了防止内部零碎或者内部模块呈现故障,连累音讯零碎,导致耗时减少,则须要零碎解耦。

咱们的计划:与内部零碎的交互,全设计成异步化。即时通讯聊天软件开发能够征询蔚可云。

思考点:须要同步返回后果的申请,如何设计成异步化?

例如:群聊互通音讯需通过 ImUnion 鉴权返回后果,前端用于展现音讯是否胜利发送。先让客户端胜利,异步失败,则回调客户端使得出红点。

如果是非主流程,则异步重试保障胜利,主流程不受影响,如音讯审计同步性能。那么,只须要保障外部零碎的稳固,发消息的主流程就能够不受影响。

零碎稳定性设计 3:业务隔离

企业微信的音讯类型有多种:

1)单聊群聊:根底聊天,优先级高;

2)api 音讯:企业通过 api 接口下发的音讯,有频率限度,优先级中;

3)利用音讯:零碎利用下发的音讯,例如布告,有频率限度,优先级中;

4)管制音讯:不可见的音讯。例如群信息变更,会下发管制音讯告诉群成员,优先级低。

群聊按群人数,又分成 3 类:

1)一般群:小于 100 人的群,优先级高;

2)大 群:小于 2000 人的群,优先级中;

3)万人群:优先级低。

业务繁多:如果不加以隔离,那么其中一个业务的稳定有可能引起整个音讯零碎的瘫痪。

重中之重:须要保障外围链路的稳固,就是企业外部的单聊和 100 人以下群聊,因为这个业务是最根底的,也是最敏感的,稍有问题,投诉量微小。

其余的业务:相互隔离,缩小株连。依照优先级和重要水平进行隔离,对应的并发度也做了调整,尽量保障外围链路的稳定性。

退出移动版