现在 IM 系统已经不仅限于文本消息的通讯了,多媒体数据占据越来越多的比重,比如:文件传输、语音通话、视频通话等。
在前面的文章(《基于需求分析模型来结构化剖析 IM 系统》)中我们分析过,“多媒体消息” 属于扩展功能需求,“点对点私信消息” 属于基础功能需求,扩展功能以基础功能为基础,基础功能稳定实现后,开发扩展功能是非常简单和快速的事情。今天我们分析一下 IM 系统的文件传输和语音通话功能关键逻辑实现,内容不复杂。
在前面关于分层架构 IM 系统所有文章的描述中,客户端与服务端之间的通讯一直是基于一条 TCP 连接进行的,也就是单通道通讯。其实,在一个具备多种功能的 IM 产品中,前后端的通讯往往都是基于多通道的,也就是每个客户端与服务端之间会建立多条连接(可能是 TCP 协议、也肯能是 HTTP 协议,还可能是 WebSocket 协议),为什么要这样设计呢?
首先,每个通道传输自己专属的数据,避免通道之间相互影响,产生阻塞或延迟,尤其是文本消息数据,需要一个专属的通讯通道;我们知道多媒体数据往往会占用较大空间,如果通过文本消息通道传输多媒体数据的话,很容易影响文本消息的及时性和可靠性。
其次,每个通道传输自己专属的数据,这从底层逻辑上就解耦了逻辑关联,降低了整个系统实现的复杂性;我们在前面的文章(《架构师晋级:直播问答系统(解析)》)中,分析过直播问答系统如何通过多通道设计系统架构,降低复杂度。
下面,我们分别分析一下如何基于 IM 系统实现文件传输和语音通话。
一、文件传输
IM 系统的文件传输逻辑流程,见下图。
基于 IM 系统传输文件,我们需要扩展消息的类型;最常见的消息类型是文本消息,可以扩展出文件消息类型、表情消息类型、语音消息类型、视频消息类型等,只是在聊天窗口中需要以不同的方式进行展示。以客户端 uid=101 给客户端 uid=102 传输文件为例,文件传输的基本逻辑流程如下:
-
客户端 uid=101 访问 APPServer,获取访问令牌; APPServer 是需要搭建的内部服务,专门用来管理访问令牌;令牌是客户端用来访问文件服务器(这里以对象存储服务 OSS 为例)的凭证;APPServer 只给合法的客户端发放令牌,毕竟 OSS 是收费的,只能供自己的客户端产品使用。
-
客户端 uid=101 凭访问令牌,将文件上传到 OSS,并记录下文件的唯一标识,文件在 OSS 中的存储位置(桶和目录)。
-
客户端 uid=101 将文件在 OSS 中存储的相关信息(桶名称、存储目录、文件标识等)封装成 IM 消息,发送到 IM 服务端;这是 IM 消息发送的基本流程,在前面的文章(《分层架构 IM 系统之消息收发功能设计与实现》)中详细分析过。
-
若客户端 uid=102 处于在线状态,IM 服务端会将文件消息直接推送到客户端,这个过程通过 “三重保障” 实现消息的可靠性(《分层架构 IM 系统之消息收发功能设计与实现》);若客户端 uid=102 处于离线状态,待登录后,会拉取相关离线消息。
-
客户端 uid=102 通过解析,发现是文件消息类型后,请求 APPServer ,获取访问 OSS 的令牌。
-
客户端 uid=102 凭访问令牌,根据解析出的文件相关信息(桶名称、存储目录、文件标识等)访问 OSS,将客户端 uid=101上传的文件,下载到本地。
这就是基于 IM 系统进行文件传输的基本流程,第 3 和第 4 步,是消息收发的基本逻辑,以此为基础引入文件存储(OSS),集成和实现对文件存储的安全访问。
二、语音通话
IM 系统的语音通话逻辑流程,见下图。
基于 IM 系统进行语音通话逻辑流程实现,与文件传输类型,都是以 IM 系统传输消息为基础,集成语音通话服务(这里以 WChat 为例进行说明);客户端 uid=101 给客户端 uid=102 打语音电话,其基本的逻辑流程如下:
-
客户端 uid=101 访问 WChat,申请一个语音通话的房间,获取房间标识和访问令牌 voiceToken;房间是语音服务的一个逻辑概念,只有进入同一个房间的客户端才能建立语音连接实现语音通话;WChat 建立 “房间” 后,该 “房间” 具有一定的时效性(比如:30秒),若对方没有及时进入到 “房间”,“房间” 会失效;想一下,我们使用微信时通过语音呼叫对方的场景,很容易理解。
-
客户端 uid=101 将房间标识信息封装成 IM 消息,发送到 IM服务端;这是 IM 消息收发的基本逻辑。
-
若客户端 uid=102 在线,IM 服务端直接将语音消息推送到客户端;若客户端 uid=102 离线,IM 系统需要通过其他方式(手机push、微信消息、短信等)及时通知到用户。
-
客户端 uid=102 通过解析,发现是语音消息类型后,向 IM 服务端发出获取 voiceToken 的请求,IM 服务端会通过访问 WChat 获取语音会话令牌;为什么客户端 uid=102 不直接访问 WChat 获取 voiceToken 呢? 一是为了安全性,只有申请房间的客户端可以直接访问 WChat,而要加入房间的客户端,则需要访问 IM 服务端,IM 过滤掉了加入房间的非法用户;二是 WChat 中的房间具有时效性,要加入房间的客户端在访问 IM 时, IM 会对房间的时效性进行判断,IM 过滤掉了没有及时加入房间的用户。
-
客户端 uid=102 根据获取的 voiceToken 和房间标识,访问 WChat,加入房间,与客户端 uid=101 建立语音会话。
不管是文件传输,还是语音通话,都是以 IM 消息通道为基础,然后集成相关服务进行扩展。
最后,总结文中关键:
-
“点对点私信” 是基础功能需求,“多媒体” 是扩展功能需求,基础功能稳定实现后,开发扩展功能是非常简单和快速的事情;
-
具备多种功能的 IM 产品中,前后端的通讯往往是基于多通道的,这样设计的原因一是为了避免通道之间的相互影响,导致数据阻塞和延迟,二是为了降低实现的复杂度;
-
基于 IM 的文件传输逻辑,以 IM 消息通道为基础,然后引入文件存储服务,实现对文件存储的安全访问;
-
基于 IM 的语言通话逻辑,以 IM 消息通道为基础,然后引入语音通话服务,实现对语音通话的安全访问。