关于即时通讯:阿里IM技术分享十深度揭密钉钉后端架构的单元化演进之路

24次阅读

共计 9363 个字符,预计需要花费 24 分钟才能阅读完成。

本文由钉钉技术专家啸台、万泓分享,为了取得更好的浏览成果,本文已对内容进行少订正和从新排版。

1、引言

钉钉后端架构的单元化工作从 2018 年开始到往年,曾经是第五个年头了。五年的工夫,钉钉单元化迭代了三个版本,从最后的毛头小子,达到往年曾经小有成就。咱们在进行单元化架构建设的过程中,除了网上能找到的比比皆是的文章外,能够间接应用的零碎更是乏善可陈,使咱们不得不从最根底的零碎开始造轮子,极大的影响建设效率。侥幸的是,近几年云原生技术的衰亡,让咱们能复用很多基础设施,进而疾速晋升咱们的单元化建设能力,助力钉钉的倒退。

明天想借此文和大家分享咱们在钉钉单元化架构施行过程中的心路历程和一些最佳实际。因波及的技术和业务面太广,本文的分享无奈做到八面玲珑,次要是想在同路人中造成共鸣,进而能复用一些架构或子系统的设计和实现思路。

学习交换:

  • 挪动端 IM 开发入门文章:《新手入门一篇就够:从零开发挪动端 IM》
  • 开源 IM 框架源码:https://github.com/JackJiang2…(备用地址点此)
    (本文同步公布于:http://www.52im.net/thread-41…)

2、系列文章

本文是系列文章的第 10 篇,总目录如下:

《阿里 IM 技术分享(一):企业级 IM 王者——钉钉在后端架构上的过人之处》
《阿里 IM 技术分享(二):闲鱼 IM 基于 Flutter 的挪动端跨端革新实际》
《阿里 IM 技术分享(三):闲鱼亿级 IM 音讯零碎的架构演进之路》
《阿里 IM 技术分享(四):闲鱼亿级 IM 音讯零碎的牢靠投递优化实际》
《阿里 IM 技术分享(五):闲鱼亿级 IM 音讯零碎的及时性优化实际》
《阿里 IM 技术分享(六):闲鱼亿级 IM 音讯零碎的离线推送达到率优化》
《阿里 IM 技术分享(七):闲鱼 IM 的在线、离线聊天数据同步机制优化实际》
《阿里 IM 技术分享(八):深度解密钉钉即时消息服务 DTIM 的技术设计》
《阿里 IM 技术分享(九):深度揭密 RocketMQ 在钉钉 IM 零碎中的利用实际》
《阿里 IM 技术分享(十):深度揭密钉钉后端架构的单元化演进之路》(* 本文)

3、术语概念
本文内容中应用了一些专有的技术名词,为了不便大家了解,我把要害的几个术语概念的缩写及其含意专门列出来,供大家参考。
次要是以下几个:
1)Geo:钉钉专有化部署单位,解决数据合规需要,Geo 间数据按需互通,并且互通数据在 Geo 外部做镜像拷贝,解决两化问题;
2)Unit: Geo 外部资源物理分区隔离的最小单位,解决 Geo 内的容灾和容量的问题;
3)L0:客户端路由,决定了用户客户端接入钉钉服务器的所属单元,用户长连贯所在的逻辑单元,起到连贯减速作用。用户接入单元;
4)L1:接入层路由,以用户为维度进行调度,即用户操作产生的单元。用户归属单元;
5)L2:业务层路由,以业务资源为维度进行调度,大部分的业务资源所在单元应该和用户调度单元统一,但一些业务无奈依照用户划分单元,如 IM 的会话,音视频的会议。业务归属单元;
6)DMB:负责钉钉利用跨单元 RPC 调用的转发,能够认为是钉钉单元化 RPC 路由中间件;
7)DMR:负责钉钉利用跨单元 MQ 音讯的转发,能够认为是钉钉单元化 MQ 路由中间件;
8)DTIM:钉钉 IM 零碎。

4、单元化架构 1.0 版:合规驱动下的部署架构

2018 年,局部大客户出于法律政策、商业秘密数据存储的要求,要求钉钉的数据存储、拜访接入、服务部署须要在其信赖的区域内。既须要满足其数据存储私有化要求,同时须要满足跨地区网络的 rt 性能要求。于是咱们联合阿里云机房部署地位、物理间隔、用户数据安全等方面登程,钉钉在客户的阿里云机房内建设了一个单元,将通讯录、IM 信息等企业数据独自存储在客户机房。

咱们通过一条专线,将两个机房逻辑串联到一起,外部通过 DMB/DMR 零碎,实现了申请互通,这就是钉钉单元化架构的 1.0 版。1.0 版比较简单,纯正是业务驱动,和支付宝单元化建设的初衷——“容灾驱动”有较大区别。两个站点通过 UID 分段,将用户划分为核心用户和专有用户。上图只是一个简化的逻辑构造,外部实现远比上图简单,然而 1.0 建设次要是从 0 到 1,和大多数异地多活的零碎较类似,这里就只简略的和大家分享一下。

5、单元化架构 2.0 版:逼出来的容量架构

2020 年是一个非凡的年份,因为疫情的起因,带给大家十分多的扭转,其中也包含钉钉。因为在线办公与教育流量的突增,开年第一天下班就给钉钉一个下马威,平峰的流量曾经和元旦跨年的持平,然而和元旦不同的是这个流量是继续的,即便节前筹备了三倍容量,也抵挡不住流量对系统的冲击。只能借助阿里云的能力,一直的扩容。

然而每天将近 30% 的流量增幅,单纯的扩容也能难保障服务的连续性,最终也遇到了扩无可扩的场景,张北机房没有机位了,有机器资源然而没有机位让咱们无力无处使。咱们不得不一直进行系统优化,同时借助限流、降级、双推等措施,勉强抗住了流量的最高峰。疫情之前,咱们始终在做高可用,然而这个高可用次要集中在容灾机制上,比方搭建容灾单元。如同支付宝一样,是因为过后光纤被挖断;又比方银行的两地三核心架构,是放心某一个地区因为人祸或者和平导致数据失落。疫情的流量给咱们上了一课,仅仅关注容灾是不够的,特地是钉钉的 DAU 从千万走向亿级别之后,更须要在容量上做出提前布局。正因如此,咱们认为“容量架构不是设计进去而是真真切切被逼出来的”,所以容量架构就成为咱们单元化外围因素之一。容量架构是将流量划分到不同单元,每个单元承载各自的流量。容灾架构是单元异样时,能保障外围的能力可用,也能够将流量动静调度到别的单元,实现服务的疾速复原。因而钉钉单元化进入了 2.0 时代,专一于容量和容灾的建设。

6、2.0 版是基于什么维度进行流量划分的?

要实现流量的划分,必然要基于一个维度进行划分,一部分到 A 单元,一部分到 B 单元。钉钉单元化架构也是参考了淘系和支付宝的单元化架构,前两者都是基于 UID 划分,钉钉单元化的第一个版本其实也是一样的,基于 UID 做拆分。然而当咱们设计容量架构时,发现基于 UID 划分无奈解决咱们的容量问题。以 IM 为例:一条音讯其实属于聊天单方的,群聊亦是如此。用户能和任意一个人聊天,这样咱们根本无法找到一个切入点来划分流量,强行依照 UID 拆分,必然导致一个用户的音讯呈现在 N 个单元,单元的自关闭就无奈做了。也有同学会说:为什么音讯不依照每个人存储,这不就能依照 UID 划分了吗?论断是不行。首先这个音讯变成了写扩散,长久化的时候会变成多单元写,其次是老本翻倍,在 DTIM 这种过亿规模的场景这条路走不通。这里能够多说一点,因为这个观点来之不易,大家都晓得,人是有惯性的,既然淘宝、支付宝甚至是微信都是 UID 划分,为什么钉钉要特立独行?过后咱们团队受到了绝大部分钉钉技术团队的挑战,继续长达将近一个月的技术选型的“争吵”,最终还是达成了一致意见。DTIM 次要有 3 个维度,别离是 UID、会话(CID)、音讯。其中会话和音讯是绑定的,而零碎中最大量的是音讯,依照第一性准则来看,肯定要将音讯划分开来,能力做到将容量划分开来的成果。咱们再来看看音视频,是依照房间维度组织流量和数据的,和 IM 又齐全不同。同样,文档其实更适宜依照企业维度来划分。不同的业务领有不同的维度,因而咱们认为:单元化最重要的找到本身“最大”的业务维度,将这个保护拆分,能力实现单元的横向扩大,咱们称之为“业务路由”。回头来看:咱们之前其实是进入了思考误区,认为淘系和支付宝都是 UID 维度,咱们也要这个维度,其实 UID 正是前者的业务维度,比方订单,也是围绕用户,并不会有交加的状况,会话就是 IM 的划分维度,因而做单元化之前要先找到属于本人的业务维度。

7、2.0 版是如何实现 IM 音讯的全局路由能力的?

7.1 概述

UID 路由有个最大的益处,就是能够依照 UID 分段,能实现高效的动态路由,也不必放心多单元之间的一致性问题。然而这种分段路由局限性也比拟显著,须要事后调配,单元之间动静调度流量和数据老本极高,而且只能反对这种数值 + 程序的场景。
在钉钉的场景中,有会话维度、房间维度、企业维度等等,想简略采纳这种预分段机制难以满足业务需要。因而咱们须要构建一个业务路由零碎(RoutingService),实现音讯流量的准确路由。

 以 IM 为例:每次音讯的发送,在单元化框架层面,会通过音讯的会话(CID),查问路由信息,如果是本单元,流量上行并长久化;如果是非本单元,路由到对应的单元中。

下图是三个会话:别离是 cid:1001、cid:1002、cid:1003,三个会话附属不同单元,不论用户从哪个单元发送音讯,都会路由到会话所在的单元。比方:用户在 Unit B 的 cid:1001 中发送音讯,当音讯进入 Receiver 之后,会先查问此 cid:1001 所在的单元,发现是 Unit A,路由框架将申请转到 A 单元,音讯在 A 单元长久化并通过 A 单元的同步协定,将数据推送到客户端。

  

 
从上图可知:每次音讯发送,都要查问路由服务,DTIM 百万的峰值,对路由必然会带来超大的压力,同时咱们能发现,路由数据在多单元实现一致性是一个微小的挑战。

7.2 边缘计算:

端到端路由在 DTIM 的场景中,会话的路由信息简直不会变更,只有当咱们决定将某些超大的会话或者企业腾挪到新单元时,才会发动路由的变更,因而会话的路由信息简直能够认为是恒定不变的。那么每次查问路由服务端,效费比太低,是极大的节约。既然路由信息简直不可变,是否将路由信息缓存呢?最常见的是应用一个集中式的 Cache 零碎,缓存 Hot 的会话,咱们也是这么做的,然而这么做还是不够,一旦 Cache 零碎生效,DTIM 还是会呈现大面积故障,而且这个百万级的申请对 Cache 也是一个极大的压力。思考到钉钉有弱小的客户端,借用边缘计算的思路,咱们将用户的会话数据缓存到客户端。对于客户端来说,也只用缓存用户本身最热的 N 会话路由数据,音讯发送时,通过 Header 将路由数据携带到服务端,服务端路由 SDK 只有做合法性和续约即可,这样就将路由流量升高了 95% 以上。当路由服务出现异常时,还能够持续应用客户端路由,将路由的可用性晋升到一个新的高度。SDK 本地会根据上行申请的返回中是否有新的路由信息,进而更新客户端路由。同时能够借助钉钉有被动下推的能力,通过同步协定将新的路由信息被动推送给客户端,使会话迁徙做到更平顺。

7.3 计算下沉:

多单元一致性对于新会话:比方小明要创立一个群聊,是应该创立在那个单元呢?如果在 A 单元创立了,当会话音讯来到 B 单元,零碎怎么能第一工夫晓得会话曾经在被绑定到 A 单元。
这里个别的形式有两种:
1)单元之间的存储系统采纳相似 DTS 的机制进行异步同步,这种机制有秒级提早;
2)在应用层被动同步,比方接入音讯队列。
这两种形式因为都是异步的起因,都会呈现不统一的问题,如果会话同时被绑定在两个单元,逻辑上会导致用户的历史音讯失落,这个是不能承受的。多地区(Region)数据同步其实是通用的技术挑战,咱们认为存储系统提供是最好的形式,正如 Google 的 Spanner 一样,这样对咱们下层才是最敌对的形式。因而咱们找到了存储的 OTS、Nuwa 团队一起共建了 GlobalTable。GlobalTable 的外围原理还是借助 Nuwa 的一致性组,组散布在多个地区,采纳多数派写入胜利即返回的原理,做到 20ms 以内的一致性写。

8、2.0 版的容灾能力
钉钉单元化的容灾能力是深度联合钉钉的业务层场景落地的,和淘系支付宝等有明确的区别。

以 DTIM 为例,最大的特点是当服务单元异样时,服务侧仍能提供最外围的服务,保障最根本的能力。实质上是因为 DTIM 是最终一致性零碎,能够短暂容许局部环节失败。

能够看一下 DTIM 发送音讯的容灾场景。当某个单元齐全不可用的状况下,用户音讯发送链路通过降级为 local 模式,在本地校验非本单元会话数据通过之后间接做音讯发送,processor 遇到非本单元的会话音讯数据能够做单元间投递做数据回放,本地是否落库可选,同步协定推送不用辨别是否为本单元会话音讯数据间接通过本单元的 topic 推送给客户端,配合用户无状态疾速迁徙能力,单元间能够实现真正的分钟级别容灾切换能力。

9、2.0 版的成绩与冲破

以上是钉钉单元化 2.0 提供给利用的外围能力,在满足容灾和容量设计需要之后,钉钉单元化给利用带来了更多的能力和设想空间。
比方:
1)疾速迁徙:当某一地区资源有余时,钉钉单元化能够将业务疾速的从 A 单元迁徙到 B 单元;
2)常态化切流:比方新建的教育会话,能够放到独立的单元;
3)热点治理:以后某一个会话过热,非凡期间能够迁徙到独立集群;
4)SLA:满足不同的 VIP 客户需要,基于不同的 SLA 和售卖价格,将 VIP 客户放到对应地单元。
外围还是咱们领有单元化能力之后,实现了多单元流量的疾速调度,为业务解决了后顾之忧。

10、2.0 版在新时代面临的新挑战

10.1 鱼和熊掌不可兼得

2022 年对钉钉来说是老本之年,老本的压力不光落到了团队,还落到了每个人身上。正如存储的 CAP 实践是一样的,咱们同时只能满足两个维度,对于流量(性能 P)、老本(C)、体验(E)也是一样,在流量不可预知和干涉的状况下,抉择老本必然导致体验受损,反之抉择体验,必然导致老本升高。进入下半年,疫情重复带来流量的重复,为了实现可控的教育老本,只能在高峰期降级局部能力,这又导致体验受损,这段时间的工单量能够窥见一斑。流量是用户侧触发的,咱们无奈干涉,只能在老本和体验之间寻求均衡。和后面提及的一样,为了减小老本的耗费这就导致咱们在扩容和缩容之间疲于奔命,反馈不及时甚至有故障的危险,这种机制不可取也不可继续。到底是要流量与老本,还是要流量与体验,给咱们技术团队带来了微小的挑战和矛盾。

10.2 商业化路在何方以后钉钉为反对大客户提供了多种解决方案,业余钉钉、专属存储与打包、专有钉钉。专属钉钉通过 APP 专属化以及局部专属性能,比方为一个企业定制一个领有独立 Logo 的 APP,能满足个别的中大型客户的业务诉求。对于大型以及超大型客户,咱们提供专有钉钉,提供专有化输入,齐全隔离的计划,比方浙政钉。随同着钉钉的商业化进入深水区,客户对钉钉提出了新的诉求,特地是数据安全与归属、互联互通、残缺的能力栈等诉求,以后钉钉输入产品状态都无奈同时地满足以上需要。前几年互联网上呈现的几起数据安全事件,数据失落与泄露,未经客户受权擅自拜访客户数据,让大多数客户不信赖服务提供商,即便服务商的平安能力曾经是业界一线能力。其实这个是能够了解的,数据即客户的生命线,数据无奈在本身可控范畴内,特地是对于很多非凡行业,这是无奈承受的,本身性命岂能假手于人。专属钉钉在面临这种客户时,火线售卖同学是无能为力。那么很多同学必定会提“如果专属钉钉满足不了需要,咱们专有钉钉不是能解决这些问题吗?”,其实单单从诉求来看,专有钉钉场景是切合客户的业务诉求,提供齐全独立运行环境、可控的数据安全。然而专有钉钉因为其独特的架构带来昂扬的售价以及前期的运维代价,对于超大型的客户来说也难以承当如此高的老本。对于钉钉本身来说,从研发到后续运维,保护一套独立体系也难以在客户侧大面积推广。

11、单元化架构 3.0 版:混合云架构

11.1 概述

钉钉单元化通过四年的倒退,在容灾和容量上做出肯定的积淀,同时实现了一些核心技术的积攒。当整体架构成熟之后,咱们也在思考,单元化是否从技术架构降级为业务架构,比方搭建独立的高可用单元,依照售卖的 SLA 提供给 VIP 客户,反对钉钉商业化的倒退。同时咱们在云原生逐渐发力,将局部外围利用放到云上,通过这一年多的运行,遇到了新的挑战,但更取得云下无奈取得的计算弹性能力,云上的弹性对云下是一个降维打击,从一个新的方向解决计算问题。如上文提到的两个外围挑战,钉钉单元化同样面临这个问题,在继续的倒退中找到了一个适合的架构方向。

基本思路是:

1)云下作为根本盘,保障外围流量的问题,毕竟云下通过团体多年的打磨,不论是稳定性还是流程的合理性都有保障;
2)云上应答低落异样的流量,比方和疫情正相干的教育流量,既保证了服务的稳定性,又能充分利用云上弹性能力,在提供残缺能力的前提下做到一个绝对较低的老本。

其次是降级 Geo 概念:
1)将 Geo 作为一个独立的业务域,实现 Geo 级别齐全独立部署,分布式云模式;
2)同时 Geo 之间按需互通,从研发体系上能做到一套代码。

因而,钉钉单元化来到了 3.0 版本,咱们称之为钉钉单元化混合云架构。
混合云次要是从两个维度来看:
第一:是云上云下,咱们认为云上云下并不是取代的关系,而是互相补充的关系,是一个长期的状态,正如很多大客户随着规模的继续扩张,最终依赖的局部外围能力必然走向自研情理一样,这能做老本的进一步升高,所以架构是一个混合云架构;
第二:业务架构上也是混合云架构,通过不同的 Geo,将不同的业务逻辑上聚合到一起,构建起一张钉钉的大网,不同 Geo 按需互通,实现了业务架构的混合。
3.0 从零碎架构上绝对于 2.0,最大的区别就是云原生技术的使用和互通网关的建设。

11.2 云原生技术:抵制零碎架构熵增的无效伎俩

近几年,互联网圈最火的技术莫过于以 Docker 为代表的云原生技术最为炽热,各大云厂商也都在不遗余力的推广云原生技术以及对应的产品。同时钉钉服务过亿 DAU 的客户,面对各种可靠性、服务连续性、并发、容灾等技术挑战,也都走到了现有技术的边界。所以咱们也在一直排汇新的技术和架构,心愿从体系与架构上升高咱们的技术复杂度,以抵制熵增。咱们在 2021 年底启动了云原生降级策略,降级云原生技术并不是为了技术而降级,而是切实面临微小的技术挑战。

1)首先咱们面临多语言的挑战:咱们以 IM 为例,IM 的外围逻辑都是应用 C ++ 构建,然而咱们罕用的中间件三大件:存储、缓存、异步队列,其中缓存和异步队列在 C ++ 客户端上长期建设有余,导致 IM 长期在应用低版本。低版本因为长时间不足保护,常常会出现异常,比方队列假死、生产不均等,导致咱们本人不得不亲自上阵批改 SDK 的代码,以至最初难以使用到产品的新能力,妨碍 IM 服务能力的晋升。

2)其次是多产品多云的挑战:咱们以阿里云为例,数据库类目下的产品,从类别上就有关系数据库、NoSQL 数据库、数仓等等,还有存储也是一样。对于咱们下层业务,其实绝大部分服务都只依赖了底层的 CURD,这么多产品,每次对接一个产品都要开发一轮。配置零碎也是一样,弹内有 Diamond,云上有 Nacos、Mse,K8s 有本人的 Configmap 等,而且这些配置零碎不像数据库有规范,而是百花齐放,然而这样却苦了咱们使用者。这些内容不是咱们的外围门路,节约大把工夫在各种产品接口的适配上,显著连累了钉钉的倒退。

3)最初就是通用的流量治理挑战:钉钉很多零碎都是最终统一的零碎,IM 就是典型的最终统一零碎,这类零碎和强同步零碎在架构设计有一个显著的区别,强统一零碎如果遇到失败,必须要继续重试直到胜利,所以个别编程上都是重试 + 退却。然而最终统一零碎不是,这类零碎容许局部节点失败,不要妨碍其余流程,失败的流量通过一个异步盘旋的队列,将数据逐渐回放回来即可。这种盘旋须要借助异步队列,而且要设计各种生产机制,比方限速、比方抛弃等等,这是一个通用的逻辑,然而每个业务方或多或少都在实现本人的盘旋零碎,反复的造轮子。又比方各种故障注入,单元化路由流量等等,要想领有这个能力,团队不得不投入人力研发。在凑合架构复杂度上,咱们次要从两个维度来屏蔽复杂度。首先代码层面咱们抉择了 DDD 模式,咱们应用 DDD 分层外围是把对外零碎的依赖全副收拢到 Infrastructure 这一层,全副采纳纯虚函数 (Interface) 对外提供接口。屏蔽底层中间件差别和细节。在架构上采纳 Sidecar 的模式,相似于 Dapr 的思维,通过规范的 GRPC 和 PB 实现利用与中间件解耦。Sidecar 中集成了各种中间件、配置零碎、灰度零碎等,等价实现了利用和中间件的解耦。上文中提到的不论是多语言挑战、多云多产品的挑战、反复造轮子等问题,都能很好的解决。

11.3 互通网关:混合架构的基石

云上云下互通,或者说多个云账户 VPC 之间的互通,

咱们常见的有两种计划:
1)其一是 VPC 间接买通,让多个 VPC 之间造成一个大的局域网,RealServer 实现点对点互通;
2)其一是两头搭建一个负载均衡器,通过裸露 EIP 实现互通。
两个计划都有本人的优缺点。
对于计划一:买通的 VPC 波及到 IP 布局,如果后期没有正当布局,后续很难买通;还有这种计划有水桶短板平安问题,一旦一个 VPC 被攻破,这张网也被攻破;然而对于外部的利用来说架构就比较简单,能够仅仅借助 K8s DNS service 就能做到服务发现。
对于计划二:最大的毛病就是两头有一个集中式的负载平衡,须要申请独立的 LB 才可拜访;然而这种计划隔离性好。对于钉钉单元化来说,波及 N 个业务方,N * M 个利用,对应 X 个 VPC,要想 VPC 之间买通,简直没有可能性,而且 VPC 买通,还面临利用之间的安全性问题。要实现 Geo 之间互通,环境之间的隔离性是根本要求,与此同时,咱们也要思考到零碎的可扩展性,所以咱们必须要构建一套独立的流量网关,实现流量加密、寻址、转发等通用能力。钉钉互通网关是构建在 Envoy 之上的零碎,双向 Ingress 和 Egress,反对 GRPC 和钉钉自研协定。具备流量治理、传输加密、单元寻址等能力。钉钉单元化借助互通网关的能力,再配合全局流控系统,咱们能够在多单元之间实现准确的流量管制和调度。

12、写在最初

随同着专属集群的继续输入,客户对专属的场景需要会越来越多,须要咱们投入更多的人力继续的建设。
比方:
1)在架构侧:首先是 Sidecar 继续强化,反对更多的中间件和环境,提供不同维度的平安能力,满足客户和利用的平安需要;
2)在运维侧:咱们须要构建多 Geo 治理能力,欠缺 Geo 和单元之间流量疾速调度能力,提供自动化的自检零碎等;
3)在交付侧:如果实现疾速交付,比方是否能做到新利用一周实现单元化革新,新 Geo 一天部署实现。这些挑战都是接下来咱们要重点投入的方向。对于规范钉钉来说,这个是咱们的根本盘,一个稳固牢靠且低成本的钉钉是咱们坚持不懈的指标,接下来咱们会加大云上流量的占比,充沛的借助云上弹性能力,实现可控的老本。明天咱们只是站在钉钉的角度上抛了一个“砖”,心愿在异地多活这个畛域激发一层浪花,欢送大家一起探讨。

13、相干材料

[1] 古代 IM 零碎中聊天音讯的同步和存储计划探讨
[2] 企业级 IM 王者——钉钉在后端架构上的过人之处
[3] 深度解密钉钉即时消息服务 DTIM 的技术设计
[4] 钉钉——基于 IM 技术的新一代企业 OA 平台的技术挑战(视频 +PPT)
[5] 企业微信的 IM 架构设计揭秘:音讯模型、万人群、已读回执、音讯撤回等
[6] IM 零碎的 MQ 消息中间件选型:Kafka 还是 RabbitMQ?
[7] 深度揭密 RocketMQ 在钉钉 IM 零碎中的利用实际
(本文同步公布于:http://www.52im.net/thread-41…)

正文完
 0