IM (Instant Messaging) 是网络上最流行的通信方式,与日常生活息息相关。 IM 软件也层出不穷,例如:微信、 QQ 、易信等。通过多年深耕和技术沉淀,云信产出了一套成熟稳定的 IM SDK 架构。它提供了 IM 的主要功能,大大降低了第三方实现 IM 功能的难度。本文主要对 IM 接口设计实践展开论述。
作者:陈吉力 网易智慧企业高级 Android 开发工程师
一、对外接口的设计准则
SDK 对外提供接口设计的基本原则是易用,易懂,易扩展,易监控。展开来可归纳为以下几个特性:
1. API 按照业务功能分类,但所有业务具有统一的调用风格。
2. API 不包含方法实现,接口的实现对调用者隐藏。
3. API 调用可跟踪。
在功能形式上, SDK 需要提供以下类型的 API :
1. 功能接口:主动调用使用其提供的功能
1.1. 同步接口:在调用线程完成函数调用,并立即返回结果。
1.2. 普通异步接口:在后台线程完成函数调用,可以添加回调函数。
1.3. 可中断异步接口:在后台线程完成函数调用,可以添加回调函数,可以中断调用。
2. 回调接口:监听数据和状态改变。
二、业务的分类
SDK 包含多种业务,一部分是基础业务,另一部分是可选业务。比如用户认证服务、群服务等是基础业务;超大群服务、第三方推送服务等是可选业务。
另外,不同的业务之间难免有相似的功能,如群服务和超大群服务中,都有添加群成员,拉取群消息等功能。因此,需要将不同的业务进行隔离,一方面方便业务功能的扩展与调整,另一方面方便函数的命名与用户的理解。
同一个业务下有多个 API ,按照调用的主动性,分为回调接口和功能接口,分别放在与业务一一对应的接口类 Observer 和 Service 中。
例如:用户认证服务下的所有回调接口和功能接口都位于 AuthServiceObserver 和 AuthService 中。其中由用户主动调用来实现功能的功能接口在 AuthService 中,如登录、登出等;而用于注册回调的回调接口都在 AuthServiceObserver 中,如监听在线状态、监听数据同步等。
每个 Service 中的功能接口根据执行的性质又分为三种,同步接口、普通异步接口和可中断异步接口。
其中同步接口在调用线程立即执行;异步接口在后台线程执行,在调用线程返回可设置回调的 InvocationFuture 类型,最终结果在主线程回调;可中断异步接口和普通异步接口相似,但是返回的是继承自 InvocationFuture 的 AbortableFuture 类型,支持中断操作,用户可以通过主动调用来中断功能接口的执行。
接口调用的线程切换流程如图 2.1 所示,业务功能和接口的分类如图 2.2 所示。
Figure 1接口调用的线程切换流程
Figure 2业务功能和接口的分类
三、API的实现
(一) API的实现方式
为了实现这些目标,并考虑到实现简单,我们选用 Java 的动态代理类模型。
外部调用者调用 API 时,得到一个动态代理(Proxy) 对象,通过 Proxy 对象,将功能接口的调用全部转接到一个实现了 InvocationHandler 接口的类 ProxyHandler 上。
再根据调用方法,执行注册/注销回调或者将调用请求分派到真正的实现类上,最后根据接口的返回类型进行返回或回调,如图 3.1 所示。
Figure 3功能调用流程
和用户服务的接口类 AuthService 和 AuthServiceObserver 一样, SDK 也为其他的所有业务定义了接口类。
所有接口类和实现类呈一一对应关系,可以方便地找到 API 对应的实现。
(二)获取Proxy对象的方法
SDK对外提供了静态方法 NimClient.getService(Class<T> clazz) 来获取业务接口类对应的动态代理类。参数填入对应的接口类即可。
例如:获取用户认证服务的接口类的方式为:
NimClient.getService(AuthService.class),获取用户认证服务观察者的接口类的方式为 NimClient.getService(AuthServiceObserver.class)。
NimClient.getService 方法同步返回一个 Proxy 对象。该对象的构造方式为懒加载,业务被调用的时候才构造对应实例。如图 3.2 所示。
Figure 4获取业务Proxy对象流程
生成 Proxy 对象基于 Proxy.newProxyInstance 方法,所有生成的 Proxy 对象都由专门的容器类来管理。
以用户认证服务为例,名列前茅次调用 NimClient.getService(AuthService.class) 获取用户认证服务的 Proxy 对象时,容器理类创建一个对应的 Proxy 对象并缓存。
之后再次获取用户认证服务 Proxy 对象时,容器类将缓存直接返回。
(三) 事物跟踪类
Invoke 函数中有一个重要的事务跟踪类 (Transaction),它记录了方法的同步异步属性、方法体和返回值要求等。Transaction 对象和他的实现方法是一一对应的。每次执行 invoke 方法,都会创建一个 Transaction 实例,并传输到真正的执行点去执行。
执行完毕后, invoke 方法根据同步异步特性以及返回值,来确定功能函数的返回结果。如果是同步函数,则直接返回结果;如果是异步函数,则根据业务需求返回 InvocationFuture 或者 AbortableFuture。
(四)API的执行方式
NimClient.getService 返回的是动态代理类 ProxyHandler,它实现了 InvocationHandler 接口的 Object invoke(Object who, Method method, Object[] args) 方法,用于代理所有功能接口。
API 执行方式,即 ProxyHandler 对 invoke 方法的实现方式,其大体步骤是加载事务、初始化判断、执行事务和返回,如图 3.3 所示。
Figure 5代理执行的简要流程
执行事务这一环节还可以细分为回调接口的执行和功能接口的执行,如果是执行回调接口,则判断是否需要回调当前状态,如果是,则立即回调。
Transaction 的执行函数是 TransactionExecutor. execute 方法,送出 Transaction 后, invoke 方法会根据同步异步属性,决定是在当前线程执行,还是在后台线程执行。用于异步执行 Transaction 的后台线程是少数的,如果有多个 Transaction 需要被异步执行,则会阻塞。
接口类的每个方法都被存进一个 Map 中, SDK 以方法签名实现了同名函数重载。执行 Transaction 时,通过方法所在的接口类找到对应的实现类,再调用对应的 invoke 方法即可。对于异步方法, invoke 方法的返回值不会被返回到上层,因此异步 API 函数的实现不用关心返回值。代理的详细执行流程如图 3.4 所示。
Figure 6代理的详细流程
(五) 异步方法的回调
对于异步方法,在 TransactionExecutor. execute 执行前,先基于 Transaction 生成对应的 AbortableFuture 的实现类 TransactionFuture ,然后将其缓存,用于稍后的回调。异步方法执行完毕后,将子类返回到调用层。
在调用可中断异步接口后,同步返回的是 AbortableFuture 实例。调用方可以直接调用abort 方法中止执行。
例如:调用了用于下载消息附件的 downloadAttachment 函数后,由于文件太大,网络状况不好等情况需要取消下载时,可以主动调用 abort 方法来终止。调用方式如图 3.5 所示。可中断异步接口对应的 abort 方法由 SDK 内部实现,调用者不需要关心其实现方式。
Figure 7abort函数调用示例
TransactionFuture 回调的基本类型为 RequestCallback,SDK 在此基本类型中定义了 onSuccess、onFailed 和 onException 函数,分别用于在成功、失败和异常情况下根据执行结果的不同,回调到不同的函数。到此整个流程结束。
四、总结
云信 IM 中,用户可以通过 NimClient.getService 方法选择业务的动态代理,然后根据业务需求在调用线程或者后台线程执行功能,最后直接返回或者回调结果。
如果调用的是可中断异步接口,用户还可以中断操作。基于动态代理的实现方式,隔离了其他业务下的对外接口,并解耦了接口和实现,配合代码混淆,更进一步的提升隔离效果。
作者介绍
陈吉力,网易智慧企业高级 Android 开发工程师。本硕就读于电子科技大学,毕业后从事云信 IM SDK Android 端的开发工作,喜爱篮球,羽毛球等。
关于网易云信
网易云信:网易智企旗下融合通信云服务专家、通信与视频 PaaS 平台。集网易 24 年 IM 以及音视频技术打造的融合通信云服务专家,稳定易用的通信与视频 PaaS 平台。提供融合通信与视频的核心能力与组件,包含 IM 即时通讯、5G 消息平台、一键登录、信令、短信与号码隐私保护等通信服务,音视频通话、直播、点播、互动直播与互动白板等音视频服务,视频会议等组件服务,并联合网易易盾推出一站式安全通信方案「安全通」。目前,网易云信已经成功发送 1.6 万亿条消息,覆盖智能终端 SDK 数累计超过 186 亿,我们期待每个智能终端都有云信的融合通信能力。
文章标题:云信IM SDK接口设计实践,发布者:网易智企,转载请注明出处:https://worktile.com/kb/p/6000