对垂直业务领域进行了解,抽象成领域模型,沉淀出通用能力和标准化体系,为后续业务赋能。 这是笔者理解的技术驱动业务。生于业务,又高于业务
笔者很荣幸可以参与到淘宝小程序的开放体系中,消息能力的开放也是里面很重要的一环,在双十一前可以借助星巴克小程序把消息方案落地,这次做个总结。
这次星巴克消息开放融合带来的挑战是:底层需要对接不同的服务体系,他们之间的协议不一致,上层业务业务又需要统一,而且整个开发迭代节奏很快。
本文主要会从垂直领域行业(包括淘系)的现状,到IM的基本概念及流程,到方案选型分层,到核心模块的设计,到后续的规划思考几个方面来讲述,做个自己的思考,让大家有个全方面的理解。
文章提纲
- 行业情况(淘外和淘内),包括IM即时通信能力和IM产品
- IM的基本概念及流程
- 方案的选型和设计
- 核心模块(消息处理中心)能力抽象,参考Koajs的中间件模式设计
- 未来规划及思考
行业情况
IM的应用场景非常广泛,除了传统的图文聊天外,时下流行的在线直播聊天室、在线教育、游戏互动等各式各样产品中都有类似的应用场景。
在集团里面应用场景也很广泛, 例如淘宝聊天(BC店铺/CC淘友),淘宝直播,即时互动场景。 对客服服务领域有阿里小蜜,都是基于即时通信能力搭建的应用产品。
在淘系外也有很多优秀的产品
- 老罗的子弹短信(老罗提出的噱头说是发送方喜欢发语音,接受方喜欢看文字。这不是语音转文字么,只是自动化了)。
- 网易七鱼(客服领域解决方案),其实它跟集团里面阿里小蜜很像(机器人,快捷回复,知识库,呼叫中心,质检,分流,热门问题推荐等)
- 腾讯的QQ,微信甚至是微视等产品
调研IM行业领域,大体的产品可以分为两个部分:第一分部为IM即时通讯能力,做消息开放。例如网易云信,腾讯IM云,阿里系的百川。 例如:子弹短信和网易七鱼是在网易云信上面搭建的产品;QQ,微信和微视是在腾讯IM云上搭建的产品。 第二部分IM产品。例如:上文提到的子弹短信,网易七鱼,QQ和微信。
基本概念
IM即时通讯是不同用户之间交流的双通通道,如下是收发消息的简单模型。
我们仔细观察上面IM产品的截图,可以发现每个产品的表现形式会有差别。但是他们基本概念是一致,也就是说领域模型是一致的。 笔者认为两个核心的概念是 会话 和 消息 的概念
- 会话session(conversation): 它是指AB通讯之间维持的一种关系,它是消息存储的载体。
- 消息message: 可以根据业务分为两大块消息,会话内消息和系统通知消息。会话内消息又可以分为基本消息和自定义消息。
基本功能
单聊
1V1 聊天,提供包括文字、图片、语音、地理位置、文件、自定义消息等多种能力,除此之外还提供消息推送功能
群聊
多人聊天服务,内置公开群、私有群、聊天室、互动直播聊天室和在线成员广播大群五种群组形态,能够适应各种群组需求的场景。
手淘千牛(CC/BC)即时通信解决方案
这次星巴克消息开放融合带来的挑战是:底层需要对接不同的服务体系,他们之间的协议不一致,上层业务业务又需要统一,而且整个开发迭代节奏很快。
由于他们的领域模型是一致的,那么划分了四个层来扩展。
- 通道层: 服务端不同通道来源
- 适配层: 协议对接通道,存储
- 能力层: 对消息进行不同的分类,对消息能力进行原子性管理。
- 功能层(组件层): 垂直业务的通用业务组件
基于这种分层,我们可以在适配层和能力层沉淀出标准化的SDK,在功能层(组件层)可以沉淀出组件物料用于复用和扩展。
业务流程抽象
对于如何构建一个完整IM系统,本文把画了一个流程图,把关键流程抽象出来。流程步骤:
- 通过appkey和用户信息从服务端获取会话及会话Token
- 建立Websocket连接,添加各个连接状态的事件(连接成功,网络错误等)
- 在连接成功后进行业务逻辑处理。 包括发送消息 和 接受消息
- 业务逻辑处理完之后断链
基于这个流程可以拓展出生命周期进行业务捕获和处理,生命周期如下:
核心模块(消息处理中心)
Koajs中间件实现机制
大家对Koajs应该比较了解,对Node HttpServer进行了分装,集团开源的Egg也是依赖于Koajs进行了二次分装和中间件扩展。笔者认为Koajs最精妙的设计在于中间件的设计思想,抽出了Context执行上下文概念(应该是一次请求的执行上下文), 摘取了Koajs中间件实现的核心源码分享。
简单代码示例
const Koa = require('koa');
const app = new Koa();
app.use(ctx => {
ctx.body = 'Hello Koa';
});
app.listen(3000);
流程介绍
初始化
startApp ---> use --> push middleware ---> listen port
一次请求发起
request --> callback --> compose ---> request ---> dispatch
重点模块解析
我们可以看到compose
是Koajs的核心模块,Koajs专门提供了一个koa-compose
的npm包。他实现了洋葱圈的原理, 同步调用由外到内,异步Promise调用由内到外。原理上就是递归原理,退出递归条件是在最后promise为空。
还有一个比较重要的设计是context
对象,除了在context
对象中挂载了很多常用功能及函数。我们也可以看到callback
对每次请求都会生成新的context(const ctx = this.createContext(req, res);
),这样就有利于对请求隔离,单次请求进行中间处理。
消息处理中心设计
消息处理中心设计的中间件,也可以称为插件体系。借鉴了Koajs的实现。根据业务需求在context
挂载了syncIds
和msgs
属性。插件是对单条数据进行处理的集合。
对消息的通道划分,通常可以分为上行消息和下行消息。
- 上行消息一般指消费者侧发送的消息到服务端。
- 下行消息一般指服务端消息触达消费者。
在用户视角,由于为了确保消息的安全性,流量以及协议编码解析需要在上行消息出口侧加编码模块,在下行消息侧入口加解码模块。设计消息统一流入到消息处理中心进行处理。
SDK标准化能力输出
基于上文概念理解,业务逻辑抽象,核心模块设计,笔者在星巴克业务中输出了一套可以同时对接旺旺服务端和手淘的服务端的标准化消息体系,业务逻辑在SDK下沉,减轻前台UI表现逻辑,从而保持UI一致性,扩展性,提升用户体验。
未来展望
笔者在上文中也提到了分层,主要分为两块:标准化SDK
和 物件物料
。 同时在领域模型的基础上归纳整合出标准的前端协议,从而构建出基础能力SDK, 进而对于不同品牌构建出品牌SDK,沉淀业务组件和标准化UI。 最终可以联合其他部门一起输出一个集团IM的白皮书。
总结
总结是更加一层的抽象,方法论可以脱离垂直业务领域,在其他领域也可以适用。
- 垂直业务,行业内现状分析。
- 基本概念,领域模型的建立。
- 业务流程抽象,核心模块设计。
PS:SDK的设计:事件模块,插件模块,代理设计模式,笔者认为都是通用且必要能力。而且这些能力就可以满足大部分业务需求