请选择 进入手机版 | 继续访问电脑版

默认
打赏 发表评论 16
想开发IM:买成品怕坑?租第3方怕贵?找开源自已撸?尽量别走弯路了... 找站长给点建议
企业微信的IM架构设计揭秘:消息模型、万人群、已读回执、消息撤回等
微信扫一扫关注!

【本文作者】:潘唐磊,腾讯WXG(微信事业群)开发工程师,毕业于中山大学。内容有修订。


1、内容概述


本文总结了企业微信的IM消息系统架构设计,阐述了企业业务给IM架构设计带来的技术难点和挑战,以及技术方案的对比与分析。同时总结了IM后台开发的一些常用手段,适用于IM消息系统。

cover-opti.png

本文已同步发布于“即时通讯技术圈”公众号,欢迎关注。公众号上的链接是:点此进入

* 推荐阅读:企业微信团队分享的另一篇《企业微信客户端中组织架构数据的同步更新方案优化实战》也值得一读。

2、名词解释


以下是本文内容中涉及到的技术名词缩写,具体意义如下:

  • 1)seq:自增长的序列号,每条消息对应一个(见:《微信的海量IM聊天消息序列号生成实践》);
  • 2)ImUnion:消息互通系统,用于企业微信与微信的消息打通;
  • 3)控制消息:即控制指令,属不可见消息,是复用消息通道的一种可靠通知机制;
  • 4)应用消息:系统应用下发的消息;
  • 5)api 消息:第三方应用下发的消息;
  • 6)appinfo:每条消息对应的唯一strid,全局唯一。同一条消息的appinfo在所有的接收方中是相同的。

3、技术背景


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

消息系统的构建与设计的过程中,面临着较多的难点。而且针对toB场景的消息系统,需要支持更为复杂的业务场景。

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

  • 1)消息鉴权:关系类型有群关系、同企业同事关系、好友关系、集团企业关系、圈子企业关系。收发消息双方需存在至少一种关系才允许发消息;
  • 2)回执消息:每条消息都需记录已读和未读人员列表,涉及频繁的状态读写操作;
  • 3)撤回消息:支持24小时的有效期撤回动作;
  • 4)消息存储:云端存储时间跨度长,最长可支持180天消息存储,数百TB用户消息需优化,减少机器成本;
  • 5)万人群聊:群人数上限可支持10000人,一条群消息就像一次小型的DDoS攻击;
  • 6)微信互通:两个异构的im系统直接打通,可靠性和一致性尤其重要。

4、整体架构设计1:架构分层


1.png

如上所示,整体架构分层如下。

1)接入层:统一入口,接收客户端的请求,根据类型转发到对应的CGI层。客户端可以通过长连或者短连连接wwproxy。活跃的客户端,优先用长连接发起请求,如果长连失败,则选用短连重试。

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

3)逻辑层:大量的微服务和异步处理服务,使用自研的hikit rpc框架,svr之间使用tcp短连进行通信。进行数据整合和逻辑处理。和外部系统的通信,通过http协议,包括微信互通、手机厂商的推送平台等。

4)存储层:消息存储是采用的是基于levelDB模型开发msgkv。SeqSvr是序列号生成器,保证派发的seq单调递增不回退,用于消息的收发协议。

5、整体架构设计2:消息收发模型


企业微信的消息收发模型采用了推拉方式,这种方式可靠性高,设计简单。

以下是消息推拉的时序图:
2.png

PS:如上图所示,发送方请求后台,把消息写入到接收方的存储,然后push通知接收方。接受方收到push,主动上来后台收消息。

不重、不丢、及时触达,这三个是消息系统的核心指标:

  • 1)实时触达:客户端通过与后台建立长连接,保证消息push的实时触达;
  • 2)及时通知:如果客户端长连接不在,进程被kill了,利用手机厂商的推送平台,推送通知,或者直接拉起进程进行收消息;
  • 3)消息可达:假如遇到消息洪峰,后台的push滞后,客户端有轮训机制进行兜底,保证消息可达;
  • 4)消息防丢:为了防止消息丢失,只要后台逻辑层接收到请求,保证消息写到接收方的存储,失败则重试。如果请求在CGI层就失败,则返回给客户端出消息红点;
  • 5)消息排重:客户端在弱网络的场景下,有可能请求已经成功写入存储,回包超时,导致客户端重试发起相同的消息,那么就造成消息重复。为了避免这种情况发生,每条消息都会生成唯一的appinfo,后台通过建立索引进行排重,相同的消息直接返回成功,保证存储只有一条。

6、整体架构设计3:消息扩散写


IM中消息分发的典型方式,一般有两种:

  • 1)扩散读;
  • 2)扩散写。

6.1扩散读


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

优点:节省存储容量。

缺点:
  • ① 每个用户需存储会话列表,通过会话id去拉取会话消息;
  • ② 收消息的协议复杂,每个会话都需要增量同步消息,则每个会话都需要维护一个序列号。

6.2扩散写


即:每条消息存多份,每个群聊成员在自己的存储都有一份。

优点:
  • ① 只需要通过一个序列号就可以增量同步所有消息,收消息协议简单;
  • ② 读取速度快,前端体验好;
  • ③ 满足更多ToB的业务场景:回执消息、云端删除。

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

缺点:存储容量的增加。

企业微信采用了扩散写的方式,消息收发简单稳定。存储容量的增加,可以通过冷热分离的方案解决,冷数据存到廉价的SATA盘,扩散读体验稍差,协议设计也相对复杂些。

下图是扩散写的协议设计:
3.png

如上图所示:

  • 1)每个用户只有一条独立的消息流。同一条消息多副本存在于每个用户的消息流中;
  • 2)每条消息有一个seq,在同个用户的消息流中,seq是单调递增的;
  • 3)客户端保存消息列表中最大seq,说明客户端已经拥有比该seq小的所有消息。若客户端被push有新消息到达,则用该seq向后台请求增量数据,后台把比此seq大的消息数据返回。

7、系统稳定性设计1:柔性策略


7.1背景


企业微信作为一款to B场景的聊天im工具,用于工作场景的沟通,有着较为明显的高峰效应(如下图所示)。

4.png

正如上图所示:工作时间上午9:00~12:00、下午14:00~18:00,是聊天的高峰,消息量剧增。工作日和节假日也会形成明显的对比。

高峰期系统压力大,偶发的网络波动或者机器过载,都有可能导致大量的系统失败。im系统对及时性要求比较高,没办法进行削峰处理。那么引入一些柔性的策略,保证系统的稳定性和可用性非常有必要。

具体的做法就是启动过载保护策略:当svr已经达到最大处理能力的时候,说明处于一个过载的状态,服务能力会随着负载的增高而急剧下降。如果svr过载,则拒绝掉部分正常请求,防止机器被压垮,依然能对外服务。通过统计svr的被调耗时情况、worker使用情况等,判定是否处于过载状态。过载保护策略在请求高峰期间起到了保护系统的作用,防止雪崩效应。

下图就是因过载被拒绝掉的请求:
5.png

7.2问题


上一小结中过载保护策略所带来的问题就是:系统过载返回失败,前端发消息显示失败,显示红点,会严重影响产品体验。

发消息是im系统的最基础的功能,可用性要求达到几乎100%,所以这个策略肯定需要优化。

7.3解决方案


解决方案思路就是:尽管失败,也返回前端成功,后台保证最终成功。

为了保证消息系统的可用性,规避高峰期系统出现过载失败导致前端出红点,做了很多优化。

具体策略如下:

  • 1)逻辑层hold住失败请求,返回前端成功,不出红点,后端异步重试,直至成功;
  • 2)为了防止在系统出现大面积故障的时候,重试请求压满队列,只hold住半小时的失败请求,半小时后新来的请求则直接返回前端失败;
  • 3)为了避免重试加剧系统过载,指数时间延迟重试;
  • 4)复杂的消息鉴权(好友关系,企业关系,集团关系,圈子关系),耗时严重,后台波动容易造成失败。如果并非明确鉴权不通过,则幂等重试;
  • 5)为了防止作恶请求,限制单个用户和单个企业的请求并发数。例如,单个用户的消耗worker数超过20%,则直接丢弃该用户的请求,不重试。

优化后,后台的波动,前端基本没有感知。

以下是优化前后的流程对比:
6.png

8、系统稳定性设计2:系统解耦


由于产品形态的原因,企业微信的消息系统,会依赖很多外部模块,甚至外部系统。

例如:与微信消息互通,发送消息的权限需要放到ImUnion去做判定,ImUnion是一个外部系统,调用耗时较长。

再如:金融版的消息审计功能,需要把消息同步到审计模块,增加rpc调用。

再如:客户服务的单聊群聊消息,需要把消息同步到crm模块,增加rpc调用。为了避免外部系统或者外部模块出现故障,拖累消息系统,导致耗时增加,则需要系统解耦。

我们的方案:与外部系统的交互,全设计成异步化。

思考点:需要同步返回结果的请求,如何设计成异步化?

例如:群聊互通消息需经过ImUnion鉴权返回结果,前端用于展示消息是否成功发送。先让客户端成功,异步失败,则回调客户端使得出红点。

如果是非主流程,则异步重试保证成功,主流程不受影响,如消息审计同步功能。那么,只需要保证内部系统的稳定,发消息的主流程就可以不受影响。

解耦效果图:
7.png

9、系统稳定性设计3:业务隔离


企业微信的消息类型有多种:

  • 1)单聊群聊:基础聊天,优先级高;
  • 2)api 消息:企业通过api接口下发的消息,有频率限制,优先级中;
  • 3)应用消息:系统应用下发的消息,例如公告,有频率限制,优先级中;
  • 4)控制消息:不可见的消息。例如群信息变更,会下发控制消息通知群成员,优先级低。

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

  • 1)普通群:小于100人的群,优先级高;
  • 2)大 群:小于2000人的群,优先级中;
  • 3)万人群:优先级低。

业务繁多:如果不加以隔离,那么其中一个业务的波动有可能引起整个消息系统的瘫痪。

重中之重:需要保证核心链路的稳定,就是企业内部的单聊和100人以下群聊,因为这个业务是最基础的,也是最敏感的,稍有问题,投诉量巨大。

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

解耦和隔离的效果图:
8.png

10、to B业务功能的设计与优化1:万人群


10.1技术背景


企业微信的群人数上限是10000,只要群内每个人都发一条消息,那么扩散量就是10000 * 10000 = 1亿次调用,非常巨大。

10000人投递完成需要的耗时长,影响了消息的及时性

万人群聊相关文章推荐阅读:


10.2问题分析


既然超大群扩散写量大、耗时长,那么自然会想到:超大群是否可以单独拎出来做成扩散读呢。

下面分析一下超大群设计成单副本面临的难点:

  • 一个超大群,一条消息流,群成员都同步这条流的消息;
  • 假如用户拥有多个超大群,则需要同步多条流,客户端需维护每条流的seq;
  • 客户端卸载重装,并不知道拥有哪些消息流,后台需存储并告知;
  • 某个超大群来了新消息,需通知所有群成员,假如push没触达,客户端没办法感知有新消息,不可能去轮训所有的消息流。

综上所述:单副本的方案代价太大

以下将介绍我们针对万人群聊扩散写的方案,做的一些优化实践。

10.3优化1:并发限制


万人群的扩散量大,为了是消息尽可能及时到达,使用了多协程去分发消息。但是并不是无限制地加大并发度。

为了避免某个万人群的高频发消息,造成对整个消息系统的压力,消息分发以群id为维度,限制了单个群的分发并发度。消息分发给一个人的耗时是8ms,那么万人的总体耗时是80s,并发上限是5,那么消息分发完成需要16s。16s的耗时,在产品角度来看还、是可以接受的,大群对及时性不敏感。同时,并发度控制在合理范围内。

除了限制单个群id的并发度,还限制了万人群的总体并发度。单台机,小群的worker数为250个,万人群的worker数为30。

万人群的频繁发消息,worker数用满,导致队列出现积压:
9.png

由于并发限制,调用数被压平,没有请求无限上涨,系统稳定:
10.png

10.4优化2:合并插入


工作场景的聊天,多数是在小群完成,大群用于管理员发通知或者老板发红包。

大群消息有一个常见的规律:平时消息少,会突然活跃。例如:老板在群里发个大红包,群成员起哄,此时就会产生大量的消息。

消息量上涨、并发度被限制、任务处理不过来,那么队列自然就会积压。积压的任务中可能存在多条消息需要分发给同一个群的群成员。

此时:可以将这些消息,合并成一个请求,写入到消息存储,消息系统的吞吐量就可以成倍增加。

在日常的监控中,可以捕获到这种场景,高峰可以同时插入20条消息,对整个系统很友善。

11.jpg

10.5优化3:业务降级


比如:群人员变更、群名称变动、群设置变更,都会在群内扩散一条不可见的控制消息。群成员收到此控制消息,则向后台请求同步新数据。

举个例子:一个万人群,由于消息过于频繁,对群成员造成骚扰,部分群成员选择退群来拒绝消息,假设有1000人选择退群。那么扩散的控制消息量就是1000w,用户收到控制消息就向后台请求数据,则额外带来1000w次的数据请求,造成系统的巨大压力。

控制消息在小群是很有必要的,能让群成员实时感知群信息的变更。

但是在大群:群信息的变更其实不那么实时,用户也感觉不到。所以结合业务场景,实施降级服务,控制消息在大群可以直接丢弃、不分发,减少对系统的调用

11、to B业务功能的设计与优化2:回执消息


11.1技术背景


回执消息是办公场景经常用到的一个功能,能看到消息接受方的阅读状态。

一条回执消息的阅读状态会被频繁修改,群消息被修改的次数和群成员人数成正比。每天上亿条消息,读写频繁,请求量巨大,怎么保证每条消息在接受双方的状态是一致的是一个难点。

11.2实现方案


消息的阅读状态的存储方式两个方案。

方案一

思路:利用消息存储,插入一条新消息指向旧消息,此新消息有最新的阅读状态。客户端收到新消息,则用新消息的内容替换旧消息的内容展示,以达到展示阅读状态的效果

优点:复用消息通道,增量同步消息就可以获取到回执状态,复用通知机制和收发协议,前后端改造小。

缺点:
  • ① 存储冗余,状态变更多次,则需插入多条消息;
  • ② 收发双方都需要修改阅读状态(接收方需标志消息为已读状态),存在收发双方数据一致性问题。

方案二

思路:独立存储每条消息的阅读状态,消息发送者通过消息id去拉取数据

优点:状态一致。

缺点:
  • ① 构建可靠的通知机制,通知客户端某条消息属性发生变更;
  • ② 同步协议复杂,客户端需要准确知道哪条消息的状态已变更;
  • ③ 消息过期删除,阅读状态数据也要自动过期删除。

企业微信采用了方案一去实现,简单可靠、改动较小:存储冗余的问题可以通过LevelDB落盘的时候merge数据,只保留最终状态那条消息即可;一致性问题下面会介绍如何解决。

12.png

上图是协议流程referid:被指向的消息id,senderid:消息发送方的msgid):

  • 1)每条消息都有一个唯一的msgid,只在单个用户内唯一,kv存储自动生成的;
  • 2)接收方b已读消息,客户端带上msgid=b1请求到后台;
  • 3)在接受方b新增一条消息,msgid=b2,referid=b1,指向msgid=b1的消息。并把msgid=b2的消息内容设置为消息已读。msgid=b1的消息体,存有发送方的msgid,即senderid=a1;
  • 4)发送方a,读出msgid=a1的消息体,把b加入到已读列表,把新的已读列表保存到消息体中,生成新消息msgid=a2,referid=a1,追加写入到a的消息流;
  • 5)接收方c已读同一条消息,在c的消息流走同样的逻辑;
  • 6)发送方a,读出msgid=a1的消息体,把c加入到已读列表,把新的已读列表保存到消息体中,生成新消息msgid=a3,referid=a1,追加写入到a的消息流。a3>a2,以msgid大的a3为最终状态。

11.3优化1:异步化


接受方已读消息,让客户端同步感知成功,但是发送方的状态没必要同步修改。因为发送方的状态修改情况,接受方没有感知不到。那么,可以采用异步化的策略,降低同步调用耗时。

具体做法是:

  • 1)接受方的数据同步写入,让客户端马上感知消息已读成功;
  • 2)发送方的数据异步写入,减少同步请求;
  • 3)异步写入通过重试来保证成功,达到状态最终一致的目的。

13.png

11.4优化2:合并处理


客户端收到大量消息,并不是一条一条消息已读确认,而是多条消息一起已读确认。为了提高回执消息的处理效率,可以对多条消息合并处理

14.png

如上图所示:

  • 1)X>>A:表示X发了一条消息给A;
  • 2)A合并确认3条消息,B合并确认3条消息。那么只需要处理2次,就能标志6条消息已读;
  • 3)经过mq分发,相同的发送方也可以合并处理。在发送方,X合并处理2条消息,Y合并处理2条消息,Z合并处理2条消息,则合并处理3次就能标志6条消息。

经过合并处理,处理效率大大提高。下图是采集了线上高峰时期的调用数据。可以看得出来,优化后的效果一共节省了44%的写入量。

15.png

11.5读写覆盖解决


发送方的消息处理方式是先把数据读起来,修改后重新覆盖写入存储。接收方有多个,那么就会并发写发送方数据,避免不了出现覆盖写的问题。

流程如下:

  • 1)发送方某条消息的已读状态是X;
  • 2)接收方a确认已读,已读状态修改为X+a;
  • 3)接收方b确认已读,已读状态修改为X+b;
  • 4)接收方a的状态先写入,接受方b的状态后写入。这最终状态为X+b;
  • 5)其实正确的状态是X+a+b。

处理这类问题,无非就一下几种办法。

方案一:因为并发操作是分布式,那么可以采用分布式锁的方式保证一致。操作存储之前,先申请分布式锁。这种方案太重,不适合这种高频多账号的场景。

方案二:带版本号读写。一个账号的消息流只有一个版本锁,高频写入的场景,很容易产生版本冲突,导致写入效率低下。

方案三:mq串行化处理。能避免覆盖写问题,关键是在合并场景起到很好的作用。同一个账号的请求串行化,就算出现队列积压,合并的策略也能提高处理效率。

企业微信采用了方案三,相同id的用户请求串行化处理,简单易行,逻辑改动较少。

12、to B业务功能的设计与优化3:撤回消息


12.1技术难点


“撤回消息”相当于更新原消息的状态,是不是也可以通过referid的方式去指向呢?

回执消息分析过:通过referid指向,必须要知道原消息的msgid。

区别于回执消息:撤回消息需要修改所有接收方的消息状态,而不仅仅是发送方和单个接收方的。消息扩散写到每个接收方的消息流,各自的消息流对应的msgid是不相同的,如果沿用referid的方式,那就需要记录所有接收方的msgid。

12.2解决方案


分析:撤回消息比回执消息简单的是,撤回消息只需要更新消息的状态,而不需要知道原消息的内容。接收方的消息的appinfo都是相同的,可以通过appinfo去做指向。

协议流程:

  • 1)用户a、b、c,都存在同一条消息,appinfo=s,sendtime=t;
  • 2)a撤回该消息,则在a的消息流插入一条撤回的控制消息,消息体包含{appinfo=s,sendtime=t};
  • 3)客户端sync到撤回的控制消息,获取到消息体的appinfo与sendtime,把本地appinfo=s且sendtime=t的原消息显示为撤回状态,并删除原消息数据。之所以引入sendtime字段,是为了防止appinfo碰撞,加的双重校验;
  • 4)接收方撤回流程和发送方一致,也是通过插入撤回的控制消息。

该方案的优点明显,可靠性高,协议简单。

撤回消息的逻辑示意图:
16.png

13、思考与总结


企业微信的IM消息架构与微信类似,但是在to B业务场景面临了一些新的挑战。结合产品形态、分析策略,通过优化方案,来确保消息系统的可靠性、稳定性、安全性。

企业微信的to B业务繁杂,有很多定制化的需求,消息系统的设计需要考虑通用性和扩展性,以便支持各种需求。例如:撤回消息的方案,可以适用于消息任何属性的更新,满足更多场景。

附录:更多精华文章


[1] 有关IM架构设计的文章:
浅谈IM系统的架构设计
简述移动端IM开发的那些坑:架构设计、通信协议和客户端
一套海量在线用户的移动端IM架构设计实践分享(含详细图文)
一套原创分布式即时通讯(IM)系统理论架构方案
从零到卓越:京东客服即时通讯系统的技术架构演进历程
蘑菇街即时通讯/IM服务器开发之架构选择
腾讯QQ1.4亿在线用户的技术挑战和架构演进之路PPT
微信后台基于时间序的海量数据冷热分级架构设计实践
微信技术总监谈架构:微信之道——大道至简(演讲全文)
如何解读《微信技术总监谈架构:微信之道——大道至简》
快速裂变:见证微信强大后台架构从0到1的演进历程(一)
17年的实践:腾讯海量产品的技术方法论
移动端IM中大规模群消息的推送如何保证效率、实时性?
现代IM系统中聊天消息的同步和存储方案探讨
微信朋友圈千亿访问量背后的技术挑战和实践总结
以微博类应用场景为例,总结海量社交系统的架构设计步骤
子弹短信光鲜的背后:网易云信首席架构师分享亿级IM平台的技术实践
IM开发基础知识补课(五):通俗易懂,正确理解并用好MQ消息队列
微信技术分享:微信的海量IM聊天消息序列号生成实践(算法原理篇)
微信技术分享:微信的海量IM聊天消息序列号生成实践(容灾方案篇)
新手入门:零基础理解大型分布式架构的演进历史、技术原理、最佳实践
一套高可用、易伸缩、高并发的IM群聊、单聊架构方案设计实践
社交软件红包技术解密(一):全面解密QQ红包技术方案——架构、技术实现等
社交软件红包技术解密(二):解密微信摇一摇红包从0到1的技术演进
社交软件红包技术解密(三):微信摇一摇红包雨背后的技术细节
社交软件红包技术解密(四):微信红包系统是如何应对高并发的
社交软件红包技术解密(五):微信红包系统是如何实现高可用性的
社交软件红包技术解密(六):微信红包系统的存储层架构演进实践
社交软件红包技术解密(七):支付宝红包的海量高并发技术实践
社交软件红包技术解密(八):全面解密微博红包技术方案
社交软件红包技术解密(九):谈谈手Q红包的功能逻辑、容灾、运维、架构等
社交软件红包技术解密(十):手Q客户端针对2020年春节红包的技术实践
社交软件红包技术解密(十一):解密微信红包随机算法(含代码实现)
即时通讯新手入门:一文读懂什么是Nginx?它能否实现IM的负载均衡?
从游击队到正规军(一):马蜂窝旅游网的IM系统架构演进之路
从游击队到正规军(二):马蜂窝旅游网的IM客户端架构演进和实践总结
从游击队到正规军(三):基于Go的马蜂窝旅游网分布式IM系统技术实践
IM开发基础知识补课(六):数据库用NoSQL还是SQL?读这篇就够了!
瓜子IM智能客服系统的数据架构设计(整理自现场演讲,有配套PPT)
阿里钉钉技术分享:企业级IM王者——钉钉在后端架构上的过人之处
微信后台基于时间序的新一代海量数据存储架构的设计实践
IM开发基础知识补课(九):想开发IM集群?先搞懂什么是RPC!
阿里技术分享:电商IM消息平台,在群聊、直播场景下的技术实践
一套亿级用户的IM架构技术干货(上篇):整体架构、服务拆分等
一套亿级用户的IM架构技术干货(下篇):可靠性、有序性、弱网优化等
从新手到专家:如何设计一套亿级消息量的分布式IM系统

[2] QQ、微信团队原创技术文章:
微信朋友圈千亿访问量背后的技术挑战和实践总结
腾讯技术分享:腾讯是如何大幅降低带宽和网络流量的(图片压缩篇)
腾讯技术分享:腾讯是如何大幅降低带宽和网络流量的(音视频技术篇)
微信团队分享:微信移动端的全文检索多音字问题解决方案
腾讯技术分享:Android版手机QQ的缓存监控与优化实践
微信团队分享:iOS版微信的高性能通用key-value组件技术实践
微信团队分享:iOS版微信是如何防止特殊字符导致的炸群、APP崩溃的?
腾讯技术分享:Android手Q的线程死锁监控系统技术实践
微信团队原创分享:iOS版微信的内存监控系统技术实践
让互联网更快:新一代QUIC协议在腾讯的技术实践分享
iOS后台唤醒实战:微信收款到账语音提醒技术总结
腾讯技术分享:社交网络图片的带宽压缩技术演进之路
微信团队分享:视频图像的超分辨率技术原理和应用场景
微信团队分享:微信每日亿次实时音视频聊天背后的技术解密
QQ音乐团队分享:Android中的图片压缩技术详解(上篇)
QQ音乐团队分享:Android中的图片压缩技术详解(下篇)
腾讯团队分享:手机QQ中的人脸识别酷炫动画效果实现详解
腾讯团队分享 :一次手Q聊天界面中图片显示bug的追踪过程分享
微信团队分享:微信Android版小视频编码填过的那些坑
微信手机端的本地数据全文检索优化之路
企业微信客户端中组织架构数据的同步更新方案优化实战
微信团队披露:微信界面卡死超级bug“15。。。。”的来龙去脉
QQ 18年:解密8亿月活的QQ后台服务接口隔离技术
月活8.89亿的超级IM微信是如何进行Android端兼容测试的
以手机QQ为例探讨移动端IM中的“轻应用”
一篇文章get微信开源移动端数据库组件WCDB的一切!
微信客户端团队负责人技术访谈:如何着手客户端性能监控和优化
微信后台基于时间序的海量数据冷热分级架构设计实践
微信团队原创分享:Android版微信的臃肿之困与模块化实践之路
微信后台团队:微信后台异步消息队列的优化升级实践分享
微信团队原创分享:微信客户端SQLite数据库损坏修复实践
腾讯原创分享(一):如何大幅提升移动网络下手机QQ的图片传输速度和成功率
腾讯原创分享(二):如何大幅压缩移动网络下APP的流量消耗(下篇)
腾讯原创分享(三):如何大幅压缩移动网络下APP的流量消耗(上篇)
微信Mars:微信内部正在使用的网络层封装库,即将开源
如约而至:微信自用的移动端IM网络层跨平台组件库Mars已正式开源
开源libco库:单机千万连接、支撑微信8亿用户的后台框架基石 [源码下载]
微信新一代通信安全解决方案:基于TLS1.3的MMTLS详解
微信团队原创分享:Android版微信后台保活实战分享(进程保活篇)
微信团队原创分享:Android版微信后台保活实战分享(网络保活篇)
Android版微信从300KB到30MB的技术演进(PPT讲稿) [附件下载]
微信团队原创分享:Android版微信从300KB到30MB的技术演进
微信技术总监谈架构:微信之道——大道至简(演讲全文)
微信技术总监谈架构:微信之道——大道至简(PPT讲稿) [附件下载]
如何解读《微信技术总监谈架构:微信之道——大道至简》
微信海量用户背后的后台系统存储架构(视频+PPT) [附件下载]
微信异步化改造实践:8亿月活、单机千万连接背后的后台解决方案
微信朋友圈海量技术之道PPT [附件下载]
微信对网络影响的技术试验及分析(论文全文)
一份微信后台技术架构的总结性笔记
架构之道:3个程序员成就微信朋友圈日均10亿发布量[有视频]
快速裂变:见证微信强大后台架构从0到1的演进历程(一)
快速裂变:见证微信强大后台架构从0到1的演进历程(二)
微信团队原创分享:Android内存泄漏监控和优化技巧总结
全面总结iOS版微信升级iOS9遇到的各种“坑”
微信团队原创资源混淆工具:让你的APK立减1M
微信团队原创Android资源混淆工具:AndResGuard [有源码]
Android版微信安装包“减肥”实战记录
iOS版微信安装包“减肥”实战记录
移动端IM实践:iOS版微信界面卡顿监测方案
微信“红包照片”背后的技术难题
移动端IM实践:iOS版微信小视频功能技术方案实录
移动端IM实践:Android版微信如何大幅提升交互性能(一)
移动端IM实践:Android版微信如何大幅提升交互性能(二)
移动端IM实践:实现Android版微信的智能心跳机制
移动端IM实践:WhatsApp、Line、微信的心跳策略分析
移动端IM实践:谷歌消息推送服务(GCM)研究(来自微信)
移动端IM实践:iOS版微信的多设备字体适配方案探讨
信鸽团队原创:一起走过 iOS10 上消息推送(APNS)的坑
腾讯信鸽技术分享:百亿级实时消息推送的实战经验
IPv6技术详解:基本概念、应用现状、技术实践(上篇)
IPv6技术详解:基本概念、应用现状、技术实践(下篇)
腾讯TEG团队原创:基于MySQL的分布式数据库TDSQL十年锻造经验分享
微信多媒体团队访谈:音视频开发的学习、微信的音视频技术和挑战等
了解iOS消息推送一文就够:史上最全iOS Push技术详解
腾讯技术分享:微信小程序音视频技术背后的故事
腾讯资深架构师干货总结:一文读懂大型分布式系统设计的方方面面
微信多媒体团队梁俊斌访谈:聊一聊我所了解的音视频技术
腾讯音视频实验室:使用AI黑科技实现超低码率的高清实时视频聊天
腾讯技术分享:微信小程序音视频与WebRTC互通的技术思路和实践
手把手教你读取Android版微信和手Q的聊天记录(仅作技术研究学习)
微信技术分享:微信的海量IM聊天消息序列号生成实践(算法原理篇)
微信技术分享:微信的海量IM聊天消息序列号生成实践(容灾方案篇)
腾讯技术分享:GIF动图技术详解及手机QQ动态表情压缩技术实践
微信团队分享:Kotlin渐被认可,Android版微信的技术尝鲜之旅
QQ设计团队分享:新版 QQ 8.0 语音消息改版背后的功能设计思路
微信团队分享:极致优化,iOS版微信编译速度3倍提升的实践总结
IM“扫一扫”功能很好做?看看微信“扫一扫识物”的完整技术实现
微信团队分享:微信支付代码重构带来的移动端软件架构上的思考
IM开发宝典:史上最全,微信各种功能参数和逻辑规则资料汇总
微信团队分享:微信直播聊天室单房间1500万在线的消息架构演进之路

即时通讯网 - 即时通讯开发者社区! 来源: - 即时通讯开发者社区!

上一篇:请教下im mobilesdk 目前是否支持web,小程序,手机客户端 多端同时在线吗下一篇:融云技术分享:全面揭秘亿级IM消息的可靠投递机制

本帖已收录至以下技术专辑

推荐方案
评论 16
楼主,漫游IM消息,客户端聊天记录搜素功能。是不是基本都是本地搜索?没有很好的办法做到服务端搜索吧?
引用:小张 发表于 2021-07-19 15:38
楼主,漫游IM消息,客户端聊天记录搜素功能。是不是基本都是本地搜索?没有很好的办法做到服务端搜索吧?

服务端有消息记录就能搜索。本地搜索是因为像微信这种,号称不存储用户聊消息(张小龙说他看不到你的聊天),做不到服务端搜索,而且也不经济。
签名: 假期就在眼前,舒服!
引用:JackJiang 发表于 2021-07-19 15:41
服务端有消息记录就能搜索。本地搜索是因为像微信这种,号称不存储用户聊消息(张小龙说他看不到你的聊天 ...

但是,消息量巨大,比如有个50-100G。那是否放到es这种中间件?那会扩散的更大的数据量了吧?
引用:小张 发表于 2021-07-19 16:33
但是,消息量巨大,比如有个50-100G。那是否放到es这种中间件?那会扩散的更大的数据量了吧?

聊天记录这种数据,对于个人而言,跟普通电商里的订单这类数据相比,价值很低。服务端要存,也最多只存一定期限内的记录。从个人而言,比如你自已,绝大多数情况下,几个月以前的聊天,我想信你再也不会再回头去看了,有啥意义。所以服务端即使存也都是热数据,热数据,除非你是微信这种量级,一般情况下,都不会有那么夸张
签名: 假期就在眼前,舒服!
引用:JackJiang 发表于 2021-07-19 20:08
聊天记录这种数据,对于个人而言,跟普通电商里的订单这类数据相比,价值很低。服务端要存,也最多只存一 ...

我这边的场景是面向企业,用户说啥,基本就要尽量满足啥。我们的聊天记录也不多,1个月也就是千来万(纯聊天,不包括应用类消息)。如果要真实现服务端搜索,有什么好架构介绍吗?
引用:小张 发表于 2021-07-19 21:45
我这边的场景是面向企业,用户说啥,基本就要尽量满足啥。我们的聊天记录也不多,1个月也就是千来万(纯 ...

你去了解一下 elasticsearch
签名: 假期就在眼前,舒服!
谢谢楼主分享
有几个问题想请教下
这里的消息收发模型,是推拉结合的方式
1、这样的方式是适合单聊群聊两种吗?
2、推拉结合的优势相比单推单拉有什么优势呢?
3、推拉结合方式推过去的只是一个通知吗?具体内容可以有什么呢?

关于消息扩散模型的方式
1、会话列表和会话消息,这里的会话指的是临时会话嘛?会话要存在服务端嘛?要怎么存储?
2、文中扩散读的缺点中,说到每个会话都会维护一个序列号,这个序列号有什么用呢?


刚开始接触IM,提问的有点多,麻烦楼主有空看到解答下哈,十分感谢

引用:逍遥小子 发表于 2021-07-20 13:05
谢谢楼主分享。
有几个问题想请教下
这里的消息收发模型,是推拉结合的方式

推拉结合,说到底就是用牺牲实时性换性能。

1、会话消息指的是聊天界面里聊天内容,会话列表你可以认为是类似于打开微信界面后首页的那个“消息”列表。
2、这个可以用来辅助消息排序等
签名: 假期就在眼前,舒服!
很硬核,要是有微信类MapReduce异步队列的方案介绍就好了
引用:Monkey 发表于 2021-07-20 19:40
很硬核,要是有微信类MapReduce异步队列的方案介绍就好了

暂时还没有这方面深入的分享文章
签名: 假期就在眼前,舒服!
发送的消息,通过MQ异步写入接收方存储,如何保证顺序性?
引用:daydayup 发表于 2021-07-31 13:14
发送的消息,通过MQ异步写入接收方存储,如何保证顺序性?

理论上说服务端是很难严格控制消息顺序的,因为顺序和异步本身就是矛盾体,不过消息id是趋势递增,客户端可对消息顺序进行兜底
签名: 假期就在眼前,舒服!
对于文章中的「柔性策略」这一块,想说一下自己的理解。

引用:im系统对及时性要求比较高,没办法进行削峰处理

这里的及时性指的应该是对「发送方消息发送状态获知」的及时性,而非「接收方接收到消息」的及时性,否则下文的Hold住请求异步处理应该并实际没有解决「及时性」的问题。

这里整个的过程我认为可以用双11寄收快递来类比,
高峰期系统压力大,偶发的网络波动或者机器过载,都有可能导致大量的系统失败->
双11包裹量剧增,分拣员忙不过来严重累垮,快递点爆仓。

im系统对及时性要求比较高,没办法进行削峰处理->
本来可以临时租用另外一个仓库用于存储快件,原仓库分拣员正常工作,实际揽收了再去修改订单状态。
但对于买家来讲,就会看到订单状态一直是处于「待揽收」的状态,内心焦急。

如果svr过载,则拒绝掉部分正常请求,防止机器被压垮,依然能对外服务->
超出快递点工作能力后,快递点就不再揽件,告知情况并让其晚点再寄。

系统过载返回失败,前端发消息显示失败,显示红点,会严重影响产品体验->
快递点居然不揽件?用户内心有怨言。

逻辑层hold住失败请求,返回前端成功,不出红点,后端异步重试,直至成功->
同样是临时租用另外一个仓库用于存储快件,但这次是及时告知用户包裹「已揽收」,原仓库分拣员正常工作,就是用户实际收到包裹可能会晚点。

当然以上只是我为方便理解举的例子,与实际快递点的流程处理可能不一致。
总结来讲,通篇文章看下来,感受最深的就是以下两点:
策略降级:没肉包就吃馒头,反正都是填饱肚子。
体验优先:干就完了,失败了我再跟你说。
引用:椎锋陷陈 发表于 2021-08-30 10:46
总结来讲,通篇文章看下来,感受最深的就是以下两点:
策略降级:没肉包就吃馒头,反正都是填饱肚子。
体 ...

说的通俗
签名: 假期就在眼前,舒服!
打赏楼主 ×
使用微信打赏! 使用支付宝打赏!

返回顶部