0%

IM在掌门1对1移动中台落地技术揭秘

全文约9000字,预计阅读时间50分钟。

背景#

IM作为目前移动互联网领域份额最高的流量入口之一,几乎深入到每个人的学习工作和生活当中,而在其他领域产品流量中,IM会作为产品能力的一部分为产品提供诸如社交、客服等核心能力。

掌门技术公众号《SocketIO高性能事件驱动模型探索》中,背景介绍中掌门在基于Socket的实时互动业务领域覆盖之广,这其中即时通信(IM)作为核心功能的覆盖是不可或缺的能力支撑,同时IM也是作为实时交互中台最核心的业务领域能力,业务触角广,接入群体大。

落地#

IM(这里只实时中台IM服务)在掌门的落地大体分为三个阶段:

  1. 概念、定位、方法论
  2. IM在中台的技术落地
  3. IM中台在业务方落地

定位分析#

中台IM优先将能力和标准方案的快速输出作为核心任务,将能力的组装下放至各自业务,中台提供的是标准零件,而业务是工厂,工厂的巨大价值就是将有限的零件组装成无限的产品形态交付用户,同时业务反过来会给作为中台的供应商提出各自更加符合其自身业务的要求,其中既有合作,亦有博弈,如何将问题抽象并达成一个平衡实现共赢,同样是对IM团队的一种考验。产品面向的是终端用户,而中台IM面向的是toB的中台业务接入方+toC终端用户的多角关系。

img

(图1)交付维恩图

这篇文章将简单介绍掌门IM在设计、开发以及为业务赋能落地中的一些思路和故事,同时也通过一些接入case描述掌门IM在中台以及为业务赋能上的定位。IM本身是个广泛的概念,这其中涉及的内容之广,在概念或者领域覆盖上每个人的理解都不尽相同,所以一个明确的定位是设计IM之初需要回答自己的问题。

中台IM面对的需求和挑战

  1. 移动性需求,移动网络接入能力
  2. 实时性需求,毫秒级的响应
  3. 协同需求,组织结构支持
  4. 多租户隔离需求,平台定位
  5. 消息丰富性需求,内置和定制消息支持
  6. 大规模需求,横向扩容支持

IM在中台的技术落地#

IM的技术落地方案和其本身所面对的具体业务和需要解决的问题有着密切关系,因此各自的实现方案以及面向的技术栈千差万别,但是IM产品作为现在流量的最大入口之一,整体的设计方向也会作为相关设计者的重要参考,同样掌门IM在设计之初就将IM定位成现代IM的设计和使用风格。

技术栈#

下面这张图谱基本上可以覆盖整个IM技术域,现代化的IM提供的不仅仅是端到端的消息投递,邮件式的对话逻辑不足以满足移动社交弱空间时间特性,体验与时效性对前后端的逻辑配合提出了很高的要求。

img

(图2)IM后端知识领域图

img

(图3)IM通信核心功能图

上述的接入核心功能图中,作为接入和投递的通用Socket网关中间件不是本篇关注重点。如何设计一个能够快速在企业落地并且能够支撑多租户接入方案,本身就是一个工程矛盾,在技术栈上,模块复用现有中台的工具框架以及基础服务是快速构建本次IM的前提。

IM消息互动四阶段#

  1. 用户接入
  2. 消息发送
  3. 消息处理
  4. 消息投递

在讲述四阶段前,我们需要先聊一聊IM消息ID。对于IM应用来说,消息ID(或称序列号)是个看似不起眼,但非常重要的东西之一。

消息ID的使用贯穿了IM技术逻辑的方方面面,比如:

1)聊天消息的顺序保证;

2)聊天消息QoS送达保证机制时的去重;

3)特定聊天消息的精确查找和匹配;

4)聊天消息的已读未读处理;

5)聊天消息的送达回执;

6)群聊消息的扩散读拉取标记;

7)… …

IM系统高度个性化的特性(设计上没有统一的标准和思路),包括聊天消息ID的生成算法在内,不同的场景定位都有不同的思路和考量。

常见的消息ID生成策略有:

1)UUID:这种方法简单直观,可以很好的保证唯一性,但对于技术洁癖的人来说ID长度会有点长,而且是无序的;

2)使用twitter开源的snowflake算法:在分布式高并发的情况下,是个不错的选择,需要用法上规避掉因子冲突和时钟回拨问题;

3)按用户使用独立的ID生成空间生成顺序的ID:比如微信的消息序列号生成策略就很不错,成本相对较高。

消息ID在IM中需要具备的特性:

  • 有序
  • 全局唯一

这里简单分享一下笔者之前使用的一个IM场景下的消息分布式ID,同snowflake思路一致,同样满足有序和全局唯一特性。

ID 长度采用 80 Bit,每 5 个 Bit ,进行一次 32 进制编码,转换为一个字符,字符取值范围是:数字 “2 ~ 9 ”和字母“A ~ B”。其中,已经去掉容易造成肉眼混淆的数字 0 和 1 (余下可用的数字就是8个了),及字母 O 和 I(余下可用的字母就是24个了),那么总可用字符就是32个(刚好可按32进制进行编码)。

这样,80 Bit 可以转换为 16 个字符,再加上 3 个分隔符( - ),将 16 个字符分为 4 组,最终得到一个 19 字符的唯一 ID ,形如:“ BD8U-FCOJ-LDC5-L789 ”。 这样设计,即可以保证生成的 ID 是有序的。

1)第一段 42 Bit:用于存放时间戳,最长可表示到 2109 年,足够开发者当前使用了。时间戳数据放在高位,可以保证生成的唯一 ID 是按时间有序的,这个是消息 ID 必须要满足的条件。

2)第二段 12 Bit:用于存放自旋转 ID 。我们知道,时间戳的精度是到毫秒的,对于一套亿级 IM 系统来说,同一毫秒内产生多条消息太正常不过了,这个自旋 ID 就是在给落到同一毫秒内的消息进行自增编号。12 Bit 则意味着,同一毫秒内,单台主机中最多可以标识 4096( 2 的 12 次方)条消息。

3)第三段 4 Bit:用于标识会话类型。4 Bit ,最多可以标识 16 中会话,足够涵盖单聊、群聊、系统消息、聊天室、客服及公众号等常用会话类型。

4)第四段 22 Bit:会话 ID 。如群聊中的群 ID ,聊天室中的聊天室 ID 等。与第三段会话类型组合在一起,可以唯一标识一个会话。其他的一些 ID 生成算法,会预留两段,分别用来标识数据中心编号和主机编号(如 SnowFlake 算法),我们并没有这样做,而是将这两段用来标识会话。这样,ID 生成可以直接融入到业务服务中,且不必关心服务所在的主机,做到无状态扩缩容。

1
2
3
4
5
6
7
public SEQID(int type, String chatId) {
int messageSes = getMessageSeq();
//取会话 ID 哈希值的低 22 位,记为 sessionIdInt:
int chatIdInt = chatId.hashCode() & 0x3FFFFF;
high_bits = getHighbits(messageSes, type, chatIdInt);
low_bits = getLowbits(high_bits, chatIdInt);
}

最后得到的ID打印结果如下:

1
2
3
DJ64-HSK6-I228-X42K
DJ64-HSK6-I24C-X42K
DJ64-HSK6-I268-X42K

IM在服务内部是个内存资源大户,性能上的优化不仅需要考虑时间复杂度,空间上也还需要葛朗台精神,时间空间互换的平衡性问题仅限于短版上的妥协,这里简单列举几项。

比如对象型ID在内存中的使用方式,在IM整个链路中很多地方都会使用到UUID作为临时的会话方案,程序中尽量避免翻译成b5cfb933-8f48-ba7b-9192-8b2ccb01e62b 这种可读样式。一个UUID由16byte(2个long参数)构造,仅需要在输出成可读形态时toString()翻译。类似的做法比如上面的SEQID,Mongo的ObjectId。

1
2
3
4
public UUID(long mostSigBits, long leastSigBits) {
this.mostSigBits = mostSigBits;
this.leastSigBits = leastSigBits;
}

同样,在二进制的链路通常使用的是byte[]这种数组结构,程序执行中,也同样需要避免翻译到可读的String内容。

比如常用的翻译语句:new String(byte[], start, length),可以看看翻译转化的过程非常昂贵。

1
2
3
4
5
6
7
8
9
public static char[] copyOfRange(char[] original, int from, int to) {
int newLength = to - from;
if (newLength < 0)
throw new IllegalArgumentException(from + " > " + to);
char[] copy = new char[newLength];
System.arraycopy(original, from, copy, 0,
Math.min(original.length - from, newLength));
return copy;
}

回到IM四阶段流程,将四阶段流程描述通过时序图来表述如下:

img

(图4)用户消息示意时序图

将上图从IM服务开始的时序节点翻译成底层的设计流程图:

img

(图5)消息执行流程图

便于知识点的垂直理解,我们将面向领域驱动的领域实施逻辑切换到面向过程的里程碑节点展开。

1)用户接入#

用户的接入在现代IM中涉及到的内容较多,多端登录、多端同步、消息漫游是复杂度较高的消息一致性问题,同时还有多平台多屏幕的体验一致性问题。

在掌门网关平台,IM共享了网关多端登录能力(篇幅问题,用户网关接入能力不详细展开),消息的一致性问题则主要由消息的唯一Id和用户登录态控制。

img

(图6)用户接入模型图

2)消息发送#

消息发送如同一次邮件的发件请求,核心元素也仅仅包括消息的目的地、消息的内容。然而现实的落地复杂度却是1比100的逻辑放大。

按照微信的逻辑,一条消息发送需要一个场景的入口(包括私聊、群聊),消息的支持类型(文本、语音、图片、视频、定位消息、小灰条通知消息、模板通知消息等等),消息指定送达人或者高亮送达逻辑的@功能,最后还有消息的状态跟踪(发送中、发送成功、发送失败)。

消息发送核心是如何抽象通用的消息格式,消息的领域模型在不同的阶段会呈现不一样的属性值,但抽象层在整个回环链路上都会保持结构的一致性,以掌门IM为例:

抽象层:

Message = Target + Content

实现层:

GroupMessage = GroupTarget + Content

消息载体:

Content的封装接口包括MetaInfo(元数据) + EventMessage

EventMessage的具体实现就是具体的消息类型:TxtMessage(文本消息)、VoiceMessage(语音消息)、ImgMessage(图片消息)、TemplateMessage(模板消息),StateMessage(比如:正在输入状态消息)等等

在群聊的链路回环上,发送一条群聊消息的简单流程:

  1. 发送端:GroupTarget标记该消息为群聊消息,并且指定发送的Group地址(GroupId),指定消息的EventMessage的类型及内容,最后附上发送端的唯一requestId(端上唯一即可)
  2. IM服务端:标记Content的MetaInfo信息(发送者的身份Id等)、标记GroupMessage的唯一消息Id
  3. 接收端:反序列化得到最终的对象模型和数据,根据不同的GroupId高亮对应小红点信息,并将消息写入本地存储。
  4. ACK:带上GroupMessage的唯一Id号以及发送端的requestId,对发送端的消息进行状态变更(发送中->发送成功)

消息序列化协议

假设消息体模型我们使用Protobuf作为序列化协议,关于Protobuf和Json的性能和自身消息体大小对应关系表参考下很久之前做的一次JMH协议对比:

Protobuf和其他协议对比主要体现在带宽和内存两方面影响,这两方面影响主要还是PB大小的控制非常优秀。

协议对比

假设:使用同样一个Socket信令:{“”, {} } ,对该信令执行1w次,生成的数据包大小对比,序列化设置:不忽略empty和null。

携带相同信息量的对象,转化成Byte数组大小,累计10000次:

  • json:740000
  • protobuf:200000

平均单个对象大小,因对象包含对象本身存储,对象头信息等消息,所以对象上的对比差异不具备协议对比体现标准:

1
2
JavaBean ProtoMessage:64Byte
JavaBean Message:48Byte

img

1
2
3
4
#序列化耗时:Jackson VS Protobuf
Benchmark Mode Cnt Score Error Units
SerializableBenchmark.jsonSerializable avgt 10 2.851 ± 0.031 ms/op
SerializableBenchmark.protoSerializable avgt 10 0.266 ± 0.008 ms/op
1
2
3
4
#反序列化耗时:Jackson VS Protobuf
Benchmark Mode Cnt Score Error Units
UnserializableBenchmark.jsonSerializable avgt 10 4.656 ± 0.058 ms/op
UnserializableBenchmark.protoSerializable avgt 10 0.402 ± 0.012 ms/op

至于在业务中选型,在于自身团队和现有技术栈对接方式习惯,在绝大部分场景下,序列化往往并不是最终的短版存在,根据存储,编解码,消息可读性等需求选择适合的协议即可。Protobuf在传输时使用标准是转化过的二进制数据,不具备直观上的可读性,但不意味着安全性的能得到保障,在Socket接入场景下依旧需要SSL证书验证服务器的可信以及传输中的数据加密需要。

3)消息处理#

消息处理时整个IM流程最核心也是最复杂的逻辑,该节点包含且不仅限于诸如下列的功能:

  • 消息的过滤:限流、敏感词
  • 消息的MetaInfo:sessionId转化UserId、黑名单、白名单用户
  • 消息存储:离线消息、历史消息
    • 离线消息:离线消息用于离线期间未送达或者送达消息失败情况下的重新投递临时存放点,离线消息是个动态且实时性要求较高的读写型消息存储,高性能情况下,离线消息会采用一+二两层缓存进行存放。
    • 历史消息:历史消息的落地按照业务使用场景分为端上存储和云端存储,对于历史消息的系统性要求包括存储性压力和实时读取压力,目前绝大部分IM使用端上存储方案,对于云端存储主要需要考虑到审计性要求和增值性服务要求。

4)消息投递#

消息投递是链路节点中最后一个阶段,在经过消息处理完的消息将带上消息的唯一身份Id,在投递之前,该消息的引用次数为1,在投递时,该消息的引用此处则是投递对象数N。

投递阶段包含的核心功能和推送系统有着较高的相似度,而往往一个完整的IM系统中,必定包含一个完整的推送系统,这里通常包含2个重要功能:

  • 信令寻址:基于网关接入的环境,需要获取用户的在线状态和接入网关的实例地址(网关IP)
  • 消息负载:将消息划分到在线用户和离线用户,在线用户通过网关进行投递,离线用户通过推送系统进行投递

在消息投递阶段,除了功能上的划分职责外,整体的技术栈同消息处理阶段几乎统一保持了高度一致性,不同点在于对消息落地方案的发散性则遵循着读写扩散原则

关于存储方案应该是IM消息类核心技术栈之一,在掌门中台IM服务中,我们同样在选型上备受容量规划的困扰。

在非自研的数据库类方案选型中,开源数据库方案或者现有的基础服务方案如果能满足现有的容量设计,那既有的存储方案依然不会成为上线后的短版,在存储方案上的选型过程依旧不能停止,容量设计是基数,流量的增长是变数,在掌门IM当前的案例中,针对各方面的考量,MQ+ES作为IM的历史消息落地方案。

笔者基于IM存储特性针对一些存储方案选型进行的多维度的对比①

Mysql ElasticSearch Mongo TiDB
索引类型 B+ FST(lucene-Trie) BTree/B+ LSM(RocksDB)
WAL 是(translog)
语法 SQL(ANSI-89/92) DLS DLS 兼容SQL
并发读写场景 读>写(内存型) 读>写 读>写 写~读
高可用 MMM 集群 集群 自动恢复 (auto-failover)
扩容操作性
API协议 TCP HTTP TCP TCP(兼容MySqlClient)

当消息走完四个阶段的流程,一个基础的IM(即时消息)就完成了整个收发逻辑,当然其中的细节处理远远比几篇文章能够介绍完的,比如群聊消息时序性问题、超大规模直播群聊问题。关于超大规模直播群聊问题在另一篇《Netty内存泄漏破案全流程》案例中有一些技术细节的介绍,这里主要围绕一些不同点探讨。

群聊和超大规模直播聊天室最大的区别在于扇出的规模上限引起的一系列蝴蝶效应,在掌门IM内部项目对接中,群聊和聊天室大致有20-30个左右的功能点差异,这些差异几乎都与容量规划的数值相关,在群组和超大聊天室服务架构中,除接入SDK和消息模型的保持逻辑一致性外,流程和服务的内部逻辑有着巨大的差异。

在上述四阶段流程中,消息投递逻辑是差异最大一个环节之一,群组的设计一般会设计一个上限数字,比如微信群考虑在500,而直播类则一般在几万到几十万不等,为了减少IM业务端点对点的循环投递,聊天室的投递扇出动作一般交给网关接入层处理。

其他的主要差异点包括但不限于:

  • 消息用户及头像的处理,聊天室一般内置在消息中
  • 聊天室在线用户列表及用户数的维护方案,聊天室一般采用micro batch方式
  • 对于存在点赞行为的功能来讲,聊天室同样采用micro batch方式

关于批量聚合,这里讲一个讨巧的定时的延迟队列设计机制实现微批次逻辑,使用一个timeRange+StepRange方案实现的延迟队列,实现microBatch的思路,需要记录上一次执行的事件

如果执行事件低于本地事件,则发出一个timeout执行,如果超过上次执行的StepRange,则立即执行一次。

异步批量化处理在Log4j2源码中有着非常详细的设计思路,该兴趣的可以参考下。

Socket网关接入问题#

Socket网关对接入业务基于Meta信息协商出不同的策略,包括协议的版本、负载灰度方式、健康检查策略等,预置策略可通过注册中心维护面向服务做到服务自省,以满足接入业务更加精细化的工作。

多媒体消息#

多媒体类消息需要IM设备具备对应的输入输出设备。

语音消息:低保真语音可以转化为base64,高保真语音消息则需要文件通道。

图片消息:预览图同样可以base64传输、原图则需要走文件通道。

模板消息:模板消息为业务提供具备定制内容的消息风格,针对在线教育场景下,在IM中比如答题器、成绩单、评价、公告消息等等。

IM为业务赋能服务落地#

IM在中台落地之后,如何为业务快速赋能落地,同样是中台团队需要回答的另一个问题,初期面向客户的开发模式使得中台自身获得一定的落地时间周期,接触一线业务的痛点难点,扩大设计初期未曾考虑的功能以及优先级的设定,这正是精益创业(Startups)的核心思想,不断设计,不断试错,共同成长。

IM在对接业务实践上,不可缺少的是对于领域等概念模型的统一认知,其次才是能力的快速提供,在对接中往往新孵化的业务接入阻力更小,而对于成熟业务的则或多或少需要一些灵活的变通。

img

(图11)领域模型图

领域模型#

  • 账号体系
  • 消息
  • 关系
  • 联系人
  • 会话

多租户#

常规来说,真正的SaaS应用往往需要满足以下两点:

  • 单实例
  • 多租户

单实例意味着系统资源层面的共享,多租户意味着应用逻辑层面的隔离。所以如何平衡好这两点,才是SaaS应用多租户设计的核心关注点。

多租户支持是中台设计核心思想,如何在中台IM服务实现业务的隔离在于IM本身服务定位,常规的软隔离方案实现的逻辑隔离是共享式服务最常用也是落地平衡性较好的方案,租户申请制是共享式多租户方案接入的第一步。

完成租户的注册后,流量和数据的隔离便可以通过租户唯一Id实现策略化的横向隔离和纵向的传递。

img

(图12)接入时序图

在内部系统实现中,基于业务主体账号体系原因,实际流程比上述流程更为丰富

流量的横向隔离:共享通道、VIP通道

DB的横向隔离:分库分表

img

(图13)共享式多租户示意图

分库分表方案#

这里以最基础的DB层的分表分库方案为例:

便于基于倍数的无缝的扩容手段,假设我们选择基于ID的模N的Range方案,对上述的IM存储领域模型进行隔离,目前IM横向扩展方案使用ShardingSphere方案。

假设分配给业务接入方bizId=10001,按照4库4表方案模4,选择DB-01。

  • 用户表:按UserId取模,按照自增方案生成
  • 群组表:按GroupId取模,按照自增方案生成
  • 联系人表:按UserId取模,联系人好友关系按照friendship冗余互为好友生成,可依次关系计算二度人脉推荐用户。

Sql优化分析分享#

基于租户ID索引的分页问题,在单表数亿记录的SSD Mysql实例中,返回能控制在毫秒级内。

在切入到具体业务之前,我们需要了解一些Mysql基础查询分析器逻辑。

  • using index :使用覆盖索引的时候就会出现
  • using where:在查找使用索引的情况下,需要回表去查询所需的数据
  • using index condition:查找使用了索引,但是需要回表查询数据(ICP功能为Mysql5.6新增,同时5.6还新增的另外一个功能MRR)②
  • using index & using where:查找使用了索引,但是需要的数据都在索引列中能找到,所以不需要回表查询数据

MySQL 在表里找到所需行的方式。包括(由左至右,由最差到最好):

1
| All | index | range | ref | eq_ref | const,system | null |

IndexConditionPushdown优化支持range、ref、eq_ref、ref_or_null类型的查询,当前支持MyISAM和InnoDB存储引擎。

Mysql如何使用索引可以参考:https://dev.mysql.com/doc/refman/8.0/en/mysql-indexes.html

假设业务A,bizId=10001,其下某用户UserId=xxxxx0001,读取其好友列表,假设按后4位取模,进入DB-01,Table-01

好友联系人表:t_friendship

1
2
3
4
5
6
7
8
9
CREATE TABLE `im`.`t_friendship`  (
`uid` bigint(0) NOT NULL,
`fid` bigint(0) NOT NULL,
`create_time` datetime(0) NOT NULL,
UNIQUE INDEX `uni_mid`(`uid`, `fid`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci;
EXPLAIN SELECT fid FROM t_friendship WHERE uid = 1 ORDER BY fid asc limit 10;
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t_friendship index uni_mid uni_mid 16 1 100.00 Using where; Using index

这种设计存在几个比较典型的基本的使用规范反例:

  • type=index很明显并不符合查询所要求的等级,至少Range级别要求。
  • id主键设计通常依照自增整型进行设计,有利于后期容量规划和b+tree索引维护机制。
1
2
3
4
5
6
7
8
9
10
11
CREATE TABLE `im`.`t_friendship2`  (
`id` int(0) NOT NULL,
`uid` bigint(0) NOT NULL,
`fid` bigint(0) NOT NULL,
`create_time` datetime(0) NOT NULL,
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `id`(`uid`, `fid`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
EXPLAIN SELECT fid FROM t_friendship2 WHERE uid = 1 and id > 1 ORDER BY id asc limit 10;
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t_friendship_copy1 ref PRIMARY,id id 8 const 1 100.00 Using where; Using index; Using filesort

假设需要实现一个基于Friendship人脉关系的朋友圈之类的功能,比如早期的好友微博方案(按时间倒叙,现在的微博方案已经改成热点+随机的推送算法介入方案),这是一个1:N:N的指数级消息体量,按照上述思路应该如何设计库表结构呢?社交系统中此类场景的设计方案已经非常多样化且成熟度都较高,划分普通用户和大V分而治之的读写扩散原则是IM很多类似场景下的主流实施方案,有兴趣的同学可以自行搜索读写扩散场景。

历史消息的存储基于业务形态可分为端上存储和服务器存储,离线消息的量级基于时间和数量的范围控制会在一段时间保持一个可控的状态,一般Redis+DB能达到热点问题和容量上的性能要求。

数据硬落地之外,缓存是IM设计中承载巨大数据流量的缓冲区,Redis作为缓存和热点资源架构选型主要依据还是容量上能做到灵活控制,具体架构方案根据是否需要引入Replication、MasterSlave、Proxy等特性,从而排除掉日常开发中可能存在不兼容的特命令,比如pub/sub、mget等。

如何确保IM服务的高可用服务和重要消息的可追溯性是目前中台IM团队阶段性定位,这里我们主要使用2种较为互补的方式展开

1.面向端回环探测,链路可达性以及延迟效率探测,端上的链路黑盒探测,主要验证网络RTT和信令送达断言。

2.全链路录制回放,链路数据落地以及场景复现,面向链路的白盒探测(beacon-sandbox),按照无侵入式的jvm agent的attach和preagent方案进行设计。

实践案例#

业务案例的接入实践是检验中台创新性、抽象性能力的标准,对于业务方来讲,接入的技术门槛、时间成本同样是核心参考因素,如何给业务方接入以足够的信心是SaaS/PaaS提供方极力做足功课的目标,这些手段可能包括成功案例的借鉴、一键接入式结果验证,同样,掌门中台IM在设计之初就考虑到SDK+场景式的代入方案,同时针对掌门内部通用Token认证做到无缝接入,业务方不再需要特别针对IM新增一个接入服务(通常对接PaaS服务时需要对接面向C端的Token接入服务),在SDK接入上做到C端优先,服务端配合的接入逻辑。

  • C端SDK
  • 服务端SDK
  • 定制和模板消息SDK

因篇幅有限,具体细节不详细说明,这里列举其中几个常见的场景。

a)基于直播+聊天室方案的直播课堂

img

b)基于互动白板、音视频+IM群组的互动课堂

img

c)基于IM+定制插件的智能客服方案

img

结语#

中台IM设计上到顶层架构设计的定位,也有底层细节设计的探索,从概念的定义,到服务器线程模型、在线状态寻址模型、群组内存模型,再到诸如基础架构提供的限流服务、BI算法部门提供的敏感词服务等等,功能地图细节无法一一展开,【植入广告】如果对中台的设计、技术底层或者相关的核心技术栈的架构师岗位非常感兴趣,欢迎关注篇尾进入内推通道加入掌门技术大家庭👏👏👏。

作为实时交互中台最核心,距离业务最近的落地平台,IM在一期开发工作就已经有若干的接入方需求,中台落地挑战很多,可能但不限于:

  • 业务的切入是否真正理解中台的定位
  • 中台是否对于业务的领域抽象做到能力上的覆盖
  • 业务和中台对于边界的划分是否默契一致
  • 中台对于未来的变化是否具备应对能力
  • 等等…

同时中台也有其自身的考量指标,包括稳定性、创新性等。

中台是一个复杂业务系统在组织层自我进化的趋势,但不具备必然性,中台不是纯粹技术演进的结果,而是由组织驱动的技术分层,这种导向性决定了中台的时空领域的受限性,没有放之四海而皆准的组织行为,中台是进化的趋势结果之一。

中台IM设计理念来源于团队成员经验和既有业务的理解,但从业务方到设计者身份的转变,还有较多工作需要逐步深入未触达以及诸多待完善的领域,这其中来自业务方的支持给中台IM落地提供了宝贵的意见,IM在技术和业务落地的历程是一段不断踩坑不断成长的过程。

另外,移动中台体系中其他核心业务推送业务也已经进入测试阶段,和音视频团队合作的基于会议场景的屏幕共享已经完成并投入使用,作为IM的补充业务,既能独立植入到比如课堂业务,也能为IM服务提供外部支撑,这些功能立足于快速为业务赋能,并时刻保持迭代持续为业务赋能。

附IM完整知识图谱:

37195

应HR小仙女们的要求,附内推二维码:

neitui

参考:

①信息来源于官方资料或者云厂商介绍

相关压测数据

https://pingcap.com/docs-cn/stable/benchmark/how-to-run-sysbench/

https://github.com/facebook/rocksdb

https://help.aliyun.com/document_detail/144258.html?spm=a2c4g.11186623.6.726.57f163b5p1879O

https://help.aliyun.com/document_detail/35264.html?spm=a2c4g.11186623.6.1473.16b34db4Q3XbyL

②具体介绍可参考官方介绍,或者《姜承尧. MySQL技术内幕:InnoDB存储引擎(第2版) 》

个人邮箱: xumin.wlt@gmail.com

Github:https://github.com/xuminwlt/

作者介绍:徐敏,开源爱好者,10年+互联网开发经验,现任掌门课堂云架构师,主要负责课堂云实时交互中台和4层网关架构设计开发工作。