企业微信作为一款办公协同的产品,聊天消息收发是最基础的功能。消息系统的稳定性、可靠性、安全性尤其重要。

消息系统的构建与设计的过程中,面临着较多的难点。而且针对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人以下群聊,因为这个业务是最基础的,也是最敏感的,稍有问题,投诉量巨大。

其余的业务:互相隔离,减少牵连。按照优先级和重要程度进行隔离,对应的并发度也做了调整,尽量保证核心链路的稳定性。

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

  1. im即时通讯开发:聊天消息的同步和存储

    IM全称是『Instant Messaging』,中文名是即时通讯.在这个高度信息化的移动互联网时代,生活中IM类产品已经成为必备品,比较有名的如钉钉.微信.QQ等以IM为核心功能的产品.当然目前微信 ...

  2. im即时通讯开发:万人群聊消息

    传统意义上的IM群聊,通常都是像微信这样的500人群,或者QQ的2000人群(QQ有3000人群,但那是单独收费的,也就意味着它并非无门槛标配,能用上的人并不多). 自从国外某号称"世界上最 ...

  3. 企业微信的IM架构设计揭秘:消息模型、万人群、已读回执、消息撤回等

    本文作者潘唐磊,腾讯WXG(微信事业群)开发工程师,毕业于中山大学.内容有修订. 1.内容概述 本文总结了企业微信的IM消息系统架构设计,阐述了企业业务给IM架构设计带来的技术难点和挑战,以及技术方案 ...

  4. im即时通讯开发:IM系统中离线消息、历史消息实践

    在如今的移动互联网时代,IM类产品已是我们生活中不可或缺的组成部分.像微信.钉钉.QQ等是典型的以 IM 为核心功能的社交产品.另外也有一些应用虽然IM功能不是核心,但IM能力也是其整个应用极其重要的 ...

  5. im即时通讯开发之后台应用保活、消息推送的噩梦

    Android P的最后一个开发者预览版(即DP5)已如期发布于2018年7月26日,根据上面这张发布路线图,相信Android P的正式版将很快到来.对于Andriod开发者来说,不管Andriod ...

  6. im即时通讯开发:IM群聊消息的已读回执功能

    我们平时在使用即时通讯应用时候,每当发出一条聊天消息,都希望对方尽快看到,并尽快回复,但对方到底有没有真的看到?我却并不知道. 一个残酷的现实是,很多时候对方其实是早就已经看到了这条消息,但出出种种原 ...

  7. IM即时通讯开发群聊消息的已读回执功能该怎么实现?

    我们平时在使用即时通讯应用时候,每当发出一条聊天消息,都希望对方尽快看到,并尽快回复,但对方到底有没有真的看到?我却并不知道.一个残酷的现实是,很多时候对方其实是早就已经看到了这条消息,但出出种种原因 ...

  8. im即时通讯开发:群聊消息如此复杂,如何保证不丢不重

    群聊已经成为主流IM软件的基本功能,不管是QQ群.还是微信群,一个群友在群内发了一条消息,那么对于IM服务器来说需要保证: 在线的群友能第一时间收到消息: 离线的群友能在登陆后收到消息. 常见的群消息 ...

  9. 即时通讯开发如何构建一套移动端消息推送系统

    消息推送作为移动端 APP 运营中的一项关键技术,已经被越来越广泛的运用. 本文追溯了推送技术的发展历史,剖析了其核心原理,并对推送服务的关键技术进行深入剖析,围绕消息推送时产生的服务不稳定性,消息丢 ...

最新文章

  1. php 清空cache,到底如何清除 cache? 我真的快瘋了
  2. 城步一中2021高考成绩查询,2017城步一中录取分数线(附高考成绩喜报)
  3. Flink流计算编程--在WindowedStream中体会EventTime与ProcessingTime
  4. 建议 Solr 用户更新 Apache POI
  5. getContentResolver().query()方法selection参数使用详解(转)
  6. 二十七、PHP框架Laravel学习笔记——模型的多对多关联
  7. Angularjs进阶笔记(2)—自定义指令中的数据绑定
  8. linux系统gromacs使用教程,GROMACS使用教程.doc
  9. Bitmap和Drawable的互相转换
  10. Leetcode-401-二进制手表
  11. MATLAB 绘制对数图操作陷阱 hold on的位置
  12. c语言代码查重,C语言过滤重复文本数据+代码【原创】
  13. Unity 自学成长路线总结
  14. Python | 实现简单的康威生命游戏
  15. 如何快速书写文件的相对路径和绝对路径
  16. 发送邮件错误常见错误码
  17. 2022中国消费者洞察
  18. 运维必备的DevOps工具链大盘点
  19. mesh 协调器 路由器_请TI技术支持和大神指点下,关于zigbee组建mesh路由网络的问题,谢谢!...
  20. 通用网络空间安全技术

热门文章

  1. 爬取贝壳上北京房屋的租赁信息
  2. proteus流水账
  3. 揪出狐狸的尾巴,HijackThis日志细解【附反劫持一般建议】
  4. 人的7大心智模式~产品设计的秘密
  5. 浅读Google三大论文
  6. android 流式布局官方,Android 流式布局
  7. SIM基本常识(PIN,PUK,IMEI,ICCID,Ki,IMSI,SMSP之间的区别)
  8. Python编程基础:已知三角形的两边长及其夹角,求第三边长
  9. brower-sync 解决webstorm不兼容
  10. 计算机网络硬件开关win7,win7系统笔记本无线网络红叉电脑网络连接不可用的解决方法...