IM 核心概念
用户:系统的使用者
消息:是指用户之间的沟通内容。通常在 IM 系统中,消息会有以下几类:文本消息、表情消息、图片消息、视频消息、文件消息等等
会话:通常指两个用户之间因聊天而建立起的关联
群:通常指多个用户之间因聊天而建立起的关联
话题:通常指多个用户订阅了某个话题而简历起得关联
终端:指用户使用 IM 系统的机器。通常有 Android 端、iOS 端、Web 端等等
未读数:指用户还没读的消息数量
用户状态:指用户当前是在线、离线还是挂起等状态
关系链:是指用户与用户之间的关系,通常有单向的好友关系、双向的好友关系、关注关系等等。这里需要注意与会话的区别,用户只有在发起聊天时才产生会话,但关系并不需要聊天才能建立。对于关系链的存储,可以使用图数据库(Neo4j 等等),可以很自然地表达现实世界中的关系,易于建模
单聊:一对一聊天
群聊:多人聊天
客服:在电商、系统管理等服务领域,通常需要对用户提供使用咨询、售后咨询等服务。这时,就需要引入客服来处理用户的咨询
消息分流:在电商、系统管理等服务领域领域,一个商家通常会有多个客服,此时决定用户的咨询由哪个客服来处理就是消息分流。通常消息分流会根据一系列规则来确定消息会分流给哪个客服,例如客服是否在线(客服不在线的话需要重新分流给另一个客服)、该消息是售前咨询还是售后咨询、当前客服的繁忙程度等等
信箱:一个收发消息的队列,可以理解为邮局的信箱,存储待处理的信件、消息。
一:即时消息系统的基本架构
整体架构设计概览图:
-
使用者眼中的聊天系统
如果我们站在一个使用者的角度从直观体验上来看,一个简单的聊天系统大概由以下元素组成:用户账号、账号关系、联系人列表、消息、聊天会话。我在这里画了一个简单的示意图:
这个应该不难理解,我来解释一下。
-
聊天的参与需要用户,所以需要有一个用户账号,用来给用户提供唯一标识,以及头像、昵称等可供设置的选项。账号和账号之间通过某些方式(比如加好友、互粉等)构成账号间的关系链。
-
你的好友列表或者聊天对象的列表,我们称为联系人的列表,其中你可以选择一个联系人进行聊天互动等操作。
-
在聊天互动这个环节产生了消息。
-
同时你和对方之间的聊天消息记录就组成了一个聊天会话,在会话里能看到你们之间所有的互动消息。
-
开发者眼中的聊天系统
从一个 IM 系统开发者的角度看,聊天系统大概由这几大部分组成:客户端、接入服务、业务处理服务、存储服务和外部接口服务。
客户端:
客户端一般是用户用于收发消息的终端设备,内置的客户端程序和服务端进行网络通信,用来承载用户的互动请求和消息接收功能。大多数 IM 系统的客户端会负责:
-
client每个设备会在本地存每一个会话,保留有最新一条消息的顺序 ID;
-
为了避免client宕机,也就是退出应用,保存在内存的消息ID丢失,会存到本地的文件中;
-
client需要在本地维护一个等待ack队列,并配合timer超时机制,来记录哪些消息没有收到ack,以定时重发;
-
客户端本地生成一个递增序列号发送给服务器,用作保证发送顺序性。该序列号还用作ack队列收消息时候的移除。
接入服务:
接入服务可以认为是服务端的门户,为客户端提供消息收发的出入口。发送的消息先由客户端通过网络给到接入服务,然后再由接入服务递交到业务层进行处理。可以把接入服务想象成一个信件管道,联通了邮局的前台和信件分拨中心。
接入服务主要有四块功能:连接保持、协议解析、Session 维护和消息推送。
-
连接保持、协议解析、Session 维护和消息推送
在很多基于私有通信协议的 IM 系统实现中,接入服务还提供协议的编解码工作,编解码实际主要是为了节省网络流量,系统会针对传输的内容进行紧凑的编码(比如 Protobuf),为了让业务处理时不需要关心这些业务无关的编解码工作,一般由接入层来处理。
另外,还有 session 维护的工作很多时候也由接入服务来实现,session 的作用是标识“哪个用户在哪个 TCP 连接”,用于后续的消息推送能够知道,如何找到接收人对应的连接来发送。
-
接入层的高可用、负载均衡、扩展性
接入层是整个服务的门户,也是第一道防护,在接入做好攻击防护可以提高整个服务的安全性和稳定性。
业务处理服务:
消息系统的处理中枢,类比人的大脑,电脑的 CPU、GPU。大多数 IM 系统的业务会包含:
用户模块:负责注册、登录、密码、基本信息维护等业务;
用户关系模块:负责好友的添加、删除、拉黑,群组的创建、加入、踢出、解散等业务;
消息模块:这是 IM 最核心的业务模块,负责消息收发、存储调度,消息通知,消息未读数维护等等;
其他业务:例如 管理后台、红包、话题、部落、广场、朋友圈、活动等其他业务。
存储服务:
这个比较好理解,账号信息、关系链,以及消息本身,都需要进行持久化存储。
一般会用到关系型数据库、非关系型数据库、文件存储 OSS等。
外部接口服务:
由于手机操作系统的限制,以及资源优化的考虑,大部分 App 在进程关闭,或者长时间后台运行时,App 和 IM 服务端的连接会被手机操作系统断开。这样当有新的消息产生时,就没法通过 IM 服务再触达用户,因而会影响用户体验。
为了让用户在 App 未打开时,或者在后台运行时,也能接收到新消息,我们会将消息给到第三方外部接口服务,来通过手机操作系统自身的公共连接服务来进行操作系统级的“消息推送”,通过这种方式下发的消息一般会在手机的“通知栏”对用户进行提醒和展示。
另外很多 IM 系统一般也会加入红包功能,相应的会对接支付渠道和接口。
二:IM 系统都有哪些特性?
从业务需求出发,IM 系统都有哪些不一样的特性。
实时性,保证消息实时触达是互动场景的必备能力。
可靠性,“不丢消息”和“消息不重复”是系统值得信赖的前置条件。
一致性,“多用户”“多终端”的一致性体验能大幅提升 IM 系统的使用体验。
安全性,“数据传输安全”“数据存储安全”“消息内容安全”三大保障方面提供全面隐私保护。
-
实时性
对于一个实时消息系统,“实时”二字很好地表达了这个系统的基本要求。
通过微信和你的好友聊天,结果等半天对方才收到,基本上也没有意愿聊了;直播场景下,如果主播的互动消息房间里的粉丝要等很长时间才能收到,也很难让粉丝们有积极参与的欲望。
了解到“实时性”在实时消息场景下的重要性后,在技术方面,我们会采用哪些手段来提升和保证这一特性呢?细节暂不展开,在第 3 部分的“轮询与长连接:如何解决消息实时到达问题”中,展开探讨“保证消息实时性”的几种方案。
-
可靠性
如果说“实时性”是即时消息被广泛应用于各种社交、互动领域的基本前置条件,那么消息的可靠性则是实时消息服务可以“被信赖”的另一个重要特性。
这里的可靠性通俗来讲,一般包括两个方面。
-
不丢消息。“丢消息”是互动中让人难以接受的 Bug,某些场景下可能导致业务可用性差,甚至不可用的情况。比如直播间“全员禁言”的信令消息丢失,就可能导致直播室不可控的一些情况。
-
消息不重复。消息重复不仅会对用户造成不必要的骚扰和困惑,可能还会导致比较严重的业务异常,比如直播间“送礼物”的消息由于某种原因被重复发出,处理不妥的话可能会导致用户损失。
那么如何做到“不丢消息”的同时,还能解决“消息重复”问题呢?对于 IM 系统可靠性的解决方案,我会在接下来的第 3 部分中的 “ACK 机制:如何保证消息的可靠投递”展开描述。
-
一致性
消息的一致性一般来是指:同一条消息,在多人、多终端需要保证展现顺序的一致性。
比如,对于单聊场景,一致性是指希望发送方的消息发送顺序和接收方的接收顺序保持一致;而对于一个群的某一条消息,我们希望群里其他人接收到的消息顺序都是一致的;对于同一个用户的多台终端设备,我们希望发送给这个用户的消息在多台设备上也能保持一致性。
缺少“一致性”保障的 IM 系统,经常会导致双方沟通过程中出现一些“奇妙的误会”,语言乱序相关的“惨案”。网络上,你可以想象一下发给下属、领导或合作方的几条重要工作内容,如果消息错乱了,后果可能会比较严重。
保证“消息的一致性”,也是考验即时消息系统的重要指标,那么具体在实战中都有哪些通用的技术能实现这个特性,一般使用 “消息序号生成器”来保证保证消息不会乱序。
-
安全性
由于即时消息被广泛应用于各种私密社交和小范围圈子社交,因此用户对于系统的隐私保护能力要求也相对较高。从系统使用安全性的角度来看,首先是要求“数据传输安全”,其次是要求“数据存储安全”,最后就是“消息内容安全”。
每一个方面实际上业界也都有比较成熟的应对方案,具体如何从这几方面入手来保障系统的整体安全性,在第 3 部分的:“HttpDNS 和 TLS:你的消息聊天内容真的安全吗”中会展开细述。
除了以上四大特性,作为一个相对高频使用的系统,消息系统在节能省电、省流量这些方面也增加了众多锦上添花的功能。
三 即时消息系统的关键技术
基础保障
消息实时性:轮询与长链接、服务端推送
在即时消息系统中,实现消息的实时传递至关重要。通常可以通过轮询和长轮询等技术,或者使用WebSocket实现双向通信来实现。
WebSocket允许有效的服务器推送,降低了服务器轮询的负担,同时减少了网络开销。WebSocket 的优点是:支持服务端推送的双向通信,大幅降低服务端轮询压力;数据交互的控制开销低,降低双方通信的网络开销;Web 原生支持,实现相对简单。
消息的可靠投递:ACK 机制
确保消息能够可靠地传递,不会丢失或重复,这对于用户的信任至关重要。ACK(确认)机制通过确认消息的接收来保证消息的可靠传递,确保消息送达和接收的一致性。
消息的一致性:消息序号生成器
消息一致性确保消息以正确的顺序显示,无论是在一对一聊天还是群聊中。消息序号生成器为每条消息分配唯一的序列号,以维护消息的顺序。
消息的安全性:HttpDNS 和 TLS
消息系统需要解决数据传输安全、数据存储安全和消息内容安全等问题。HttpDNS和TLS(传输层安全性)等技术在确保消息系统整体安全性方面发挥着关键作用。
解决网络不确定性:智能心跳
为了处理网络条件的不确定性,智能心跳机制有助于保持连接稳定,减少不必要的重连或断开。
性能提升
更快的媒体消息发送(分片上传)
为了提高发送包含图片、音频和视频等媒体内容的消息的速度,可以采用分片上传技术。这些技术允许系统将大文件分成小块发送,提高了效率。
更流畅的媒体播放和浏览(CDN加速)
内容分发网络(CDN)加速可优化媒体消息的传递,确保用户体验流畅的媒体内容播放和快速浏览。
服务模块水平扩展(Docker容器化)
Docker容器化使得服务模块可以水平扩展,通过添加更多容器来处理增加的负载。
消息收发链路监控(端到端追踪)
通过端到端追踪监控整个消息传递过程,有助于识别和解决消息传递链路中的性能瓶颈和问题。
高可用性(流控和熔断)
实施速率限制和熔断机制可以确保高可用性,防止过载,并为系统提供容错性。
未来趋势
-
AI和机器学习在用户体验改进中的作用
AI驱动的聊天机器人和预测输入技术将继续改进即时消息系统的用户体验。
-
区块链在去中心化通信中的角色
区块链技术可能在创建注重安全和隐私的去中心化通信平台方面发挥作用。
-
新兴技术及其潜在影响
关注新兴技术及其对即时消息系统的潜在影响对于保持竞争力并满足不断变化的用户期望至关重要。