Skip to main content

即时通讯总览

即时通讯是主要解决产品内即时通信(Instant Messaging)、实时数据同步等需求,其设计上的主要目标是:

  • 支持为现有应用快速加入多种通讯能力

    我们很多客户的产品都已经达到一个比较稳定的形态,即时通讯只是其中一个锦上添花的功能,所以如何和现有系统无缝集成,是我们设计上一个重要的出发点。即时通讯服务可以在应用账户系统独立的情况下,快速接入并稳定安全地运行。

    我们支持了多种典型通讯场景,提供了丰富的 UI 库和脚手架来帮助开发者快速接入。并且考虑到业务运行环境,我们提供了全平台支持的 SDK。

  • 强大的自定义机制满足业务各种扩展需求

    我们默认支持了文本、图片、音视频、地理位置、二进制等多种类型的消息收发,同时也允许产品开发者来扩展自己的消息类型和 UI 样式。并且在基本功能之外,我们也支持更多高阶需求,例如消息撤回与修改、@ 成员提醒、暂态消息、「已读」回执、离线推送、敏感内容过滤等等与消息收发相关的功能,或者超大规模用户参与的「开放聊天室」,以及类似于微信公众号的「系统对话」,在这里都可以得到满足。

  • 安全和权限控制

    我们始终把系统安全性放在首要位置,客户端与云端使用 WebSocket 全双工通讯,全程 TLS 加密传输。在用户登录和操作权限的控制上,我们专门设计了第三方操作签名的机制,让应用层在快速接入的同时,也可以实时、完整地控制用户在即时通讯系统内的所有活动。

  • 最大限度降低客户的生产运维成本

    我们提供专业的技术支持服务,富有经验的资深工程师 7 × 24 小时对接,以帮助开发者快速、有效地完成产品集成,缩短开发周期。此外在产品运营阶段,让开发者彻底摆脱后端系统日常的运维细节和突发的软硬件故障处理,也不用关心用户量和流量的变化。帮助客户在享受高品质技术服务的同时,也可以最大限度降低生产运维成本,并且以更快的速度推进产品迭代,是我们始终追求的目标。

即时通讯服务现在已经被广泛使用在应用内社交、工作协同、客服系统、超大型赛事和电视直播、以及游戏状态同步等多种业务场景之中。

功能和特性

即时通讯服务提供的主要功能有:

  • 基本聊天功能,包括:

    • 支持多种聊天场景。除了普通的单聊、群聊之外,我们还提供不限人数的「开放聊天室」,适合活动直播、公开课、游戏中的世界聊天等海量用户在一个群里互动的场合,也提供了可用来实现应用内的公众号、服务号的「系统对话」,还有专为客服系统准备的「临时对话」。通过提炼不同场景的共通需求,我们提供了功能各异但接口一致的解决方案。
    • 用户之间可以发送多种多样的消息,如文本、图片、语音、音视频、地理位置等,也可以发送 二进制消息,以及更多的应用层自定义消息。
    • 聊天消息自动保存在云端,支持各种复杂的查找和翻页方式。
  • 特殊的消息收发需求。除了普通的消息收发之外,我们还支持:

    • 带有提醒功能的 @ 消息(如微信里面的 @ 某人)
    • 消息的 撤回和修改
    • 消息送达和对方已读的 回执通知
    • 群聊里面为了避免过于干扰,允许用户开启 消息免打扰 开关
    • 发送譬如聊天过程中「某某正在输入…」这样的 状态信息
    • 在消息接收方离线时,自动转为 推送通知(Push Notification)
    • 对于大型的开放聊天室,为了防止重要消息被淹没或丢弃,支持不同 优先级 的发送选项,确保重要的消息能优先、迅速送达客户端
  • 多端登录与消息同步

    现在一个用户使用多个设备登录已经是比较常见的需求,我们既支持单个账号在多个设备同时登录、即时通讯同步到所有设备,也支持 单点登录,可由业务层自主选择。 移动设备网络不稳定也是常态,聊天过程中用户难免会偶尔掉线,我们的 消息同步机制 可以确保用户消息及时得到同步,重要消息从不丢失。

  • 管理与运营支持

    对于聊天消息,我们默认提供了 实时过滤敏感内容 的能力,允许各个产品设置自己的敏感词列表,并且也支持开发者实现自己的敏感词过滤插件,来确保产品运营层面合规合法。

  • 安全控制

    任何终端用户要开启即时通讯服务,只需要提供一个唯一标识自己的 clientId 即可,这种与产品自有账户系统解耦合的方式,带来了集成的便利,也可以促使通讯服务商专注做好底层的「信使」角色。 同时我们也提供 第三方鉴权 的机制,通过在聊天流程中加入开发者服务器签名授权这一环节,来确保通讯操作的安全。 而且,即时通讯 SDK 与云端是 WebSocket 全双工通讯,且全程使用 TLS 安全加密。

  • 强大的业务扩展能力

    对于很多典型的需求,我们提供了默认的实现,而为了支持业务的多样性和特殊性,我们也提供了丰富的扩展机制:

    • 为了和产品自有用户系统进行对接,我们提供了第三方操作鉴权的扩展接口,确保在用户登录、创建/加入/退出对话群组、以及拉取聊天记录时,所有操作都得到了授权。
    • 同时我们还支持开发者对消息传递的过程进行 hook 处理,在消息到达云端但是还没有投递之前和投递之后,分别完成自定义的处理逻辑,例如过滤掉竞品的品牌,以及自定义离线推送消息,等等。
    • 我们也支持通过简单的 web hook 来完成云端和应用后端的消息同步。
    • 在提供移动端的 SDK 之外,我们还提供了 REST API,以帮助产品在可信环境下更好地实现业务处理。

    我们相信灵活性和扩展性也是云服务的核心竞争力。

全平台 SDK 和 Demo 支持

目前,我们提供了主流平台的客户端 SDK,而且它们源代码都是公开的,开发者可以在我们的 GitHub 账户 下自由下载,可以与我们工程师同步讨论遇到的问题和需求。

在 SDK 之外,我们也公开了一些 Demo 项目来帮助开发者快速熟悉我们的产品,详见页眉导航栏的 下载 > Demos 链接。

核心概念说明

在深入了解之前,我们先跟大家解释几个核心概念,这些概念在 API 或者后面的开发指南中都会出现,了解它们会让后续的文档阅读变得简单和轻松很多。

clientId、用户和登录

即时通讯服务中的每一个终端称为一个「Client」。Client 拥有一个在应用内唯一标识自己的 ID(clientId)。这个 ID 由应用自己定义,必须是 只由英文字母、数字、半角下划线与半角短横线组成,不以数字开头,不超过 64 个字符的字符串。在大部分场合,Client 都可以对应到应用中的某个「用户」,但是并不是只有真的用户才能作为「Client」,你完全可以把一个探测器当成一个「Client」,把它收集到的数据通过即时通讯服务广播给更多「人」。

要使用即时通讯服务,每一个终端设备需要首先建立与即时通讯云端的 WebSocket 长连接,并使用唯一的 clientId 来加入即时通讯服务,我们把这一过程称为「登录」。请注意这里的登录仅仅指客户端登录即时通讯服务,与应用层面的用户账户注册登录是不一样的。

默认情况下,即时通讯服务允许一个 clientId 在多个不同的设备上登录,也允许一个设备上有多个 clientId 同时登录。如果使用场景中需要限制用户只在一处登录,可以在登录时明确设置当前设备的 tag,当云端检测到同一个 tag 的设备出现冲突时,会自动踢出已存在设备上的登录状态。开发者可以根据自己的应用场景选择合适的登录方式。

客户端通过即时通讯 SDK 完成登录后,开发者就不必再关心底层的网络连接状态,SDK 会自动为开发者保持连接状态,并在网络状态变化之后进行自动重连。当应用在前台时 SDK 会保持连接,而当应用退到后台时连接会自动断开。我们默认会激活平台原生的推送服务,来保证消息及时送达。

对话(Conversation)

用户登录之后,与其他人进行消息沟通,即为开启了一个「对话(Conversation)」。在即时通讯服务中,「对话」包含了沟通的用户群体(成员),也是所有消息依托的媒介:消息都是由某一个 Client 发往一个「对话」。终端用户在开始聊天之前,需要先创建或者加入一个对话,然后再邀请其他人进来(可选),之后所有参与者在这个对话内进行交流。

用户每创建一个对话,就会在云端的 _Conversation 表中增加一条记录,可以进入 开发者中心 > 你的游戏 > 游戏服务 > 云服务 > 数据存储 > 结构化数据 来查看该数据。一个「对话」在创建之后,我们还可以给他指定一些应用层的属性,例如名字、成员、以及自定义的扩展属性,等等。对话的各个属性与 _Conversation 表中字段的对应关系为:

属性名表字段类型约束说明
namenameString可选对话的名字,可为群组命名。
attributesattrObject可选自定义属性,供开发者扩展使用。
conversationIdobjectIdString对话 ID(只读),由云端为该对话生成的一个全局唯一的 ID。
creatorcString对话创建者的 clientId(只读)。
membersmArray普通对话的所有参与者(仅针对普通对话,聊天室和系统对话并不支持持久化的成员列表,具体的开发指南中会有详细解释)。
mutemuArray将对话设为静音的参与者,这部分参与者不会收到推送(仅对 iOS 以及开启了混合推送的 Android 用户有效,具体的开发指南中会有详细解释)。
lastMessageAtlmDate对话中最后一条消息的发送或接收时间。
transienttrBoolean可选对话类型标志,是否为聊天室,后面会说明。
systemsysBoolean可选对话类型标志,是否是系统对话,后面会说明。
uniqueuniqueBoolean可选内部字段,对话类型标志,标记根据成员原子创建的对话,后面会说明。

虽然我们统一使用 _Conversation 表来存储所有对话,但是根据业务场景的不同我们 SDK 里面提供了多种不同的对话类型可供选择。

业务场景的需求

在解释对话类型之前,我们先列举一下即时通讯可能的使用场景。

  • 单聊/私聊

    就是两个 Client 之间的对话,公开与否(能否让其他人看到这个对话存在)由应用层自己控制。通常的业务场景里它是私密的,并且加入新的成员之后,会切换成新的群聊(当然,也可以依然不离开当前对话,这一点还是由应用层来决定)。

  • 群聊

    就是两个(含)以上 Client 之间的对话,通常可以添加和删除成员,并且会赋予群聊一个名字,例如「家人群」、「朋友群」、「部门同事群」等等。随着成员的减少,群聊也可能只有两个甚至一个成员(成员的多少并不是区分群聊和单聊的关键)。群聊能否公开(譬如支持名字搜索),由应用自己决定。

  • 聊天室

    游戏中的世界聊天,直播产品使用的开放聊天室、弹幕、网页直播等都可以抽象成开放「聊天室」,它与群聊类似,都是多人参与的群组,但是也有一些区别:其一在于聊天室人数可能远大于群聊人数;其二在于聊天室强调的是在线人数,所有参与者进入聊天界面就算加入,关闭界面就算退出,所以聊天室不需要离线消息和推送通知,在线成员数比具体成员列表更有意义。

  • 公众号、机器人

    很多产品都会加入类似微信的公众号、服务号的功能,让一些特殊的账号可以给订阅用户发全员广播,也可以和特定用户进行一对一的信息交流。也有一些业务需要实现一个智能机器人的功能,可以自动与其他用户进行交流,解决客服或者问答类的需求。

  • 临时客服通道

    有一些客服系统,会为每一个反馈问题的终端用户建立一个与在席客服的临时沟通渠道,在通道内用户和客服人员如单聊一般进行沟通,随着问题的解决自动关闭该通道。

即时通讯系统设计了四种类型的「对话」来满足不同的需求,下面我们看看如何把上面的业务场景映射到具体的「对话」类型。

普通对话(Conversation)

这是我们使用最多的「对话」,一般的单聊和群聊都可以通过它来实现。普通对话支持的功能有:

  • 成员之间发送和接收消息
  • 允许增加、删除成员(最大成员数不超过 500),且会全局通知成员变动事件
  • 支持查询成员在线状态
  • 支持更多的消息收发选项,例如 @ 成员提醒消息、撤回和修改消息、暂态消息、消息送达和已读的回执通知、Will 消息、离线推送通知等等
  • 部分成员离线状态下,可以收到消息推送通知,并且上线之后会进行消息同步,确保不丢消息
  • 消息记录自动保存在云端,支持多种查询方式

建议:开发者将单聊/群聊、私密/公开等属性存入到 Conversation.attributes 之中,在应用层进行区分。

聊天室(Chat Room)

专门用来处理不限人数的「聊天室」的这种需求的「对话」(在老版本 SDK 中也叫 Transient Conversation,在 _Conversation 表中,以 trtrue 来标记)。与普通对话一样,它支持创建、自身主动加入、自身主动退出对话等操作,消息记录会被保存并可供获取,但其不同之处在于:

  • 不限成员上限,没有固定成员概念,加入即为成员,断线即为退出(m 列将被忽略)
  • 不支持查询成员列表,你可以通过相关 API 查询在线人数
  • 不支持离线消息、离线推送通知、消息回执等功能
  • 没有成员加入、离开的通知
  • 不支持邀请加入、踢出成员这两个操作
  • 一个用户一次登录只能加入一个聊天室,加入新的聊天室后会自动离开旧的聊天室
  • 加入之后如果半小时内断网重连会自动加入原聊天室,超过这个时间则需要重新加入

建议:虽然「聊天室」不限制成员数量,但从实际经验来看,如果人数过多,那么聊天室内消息被放大的效果会非常明显,对于终端用户而言即表现为过量消息不断刷屏,反而影响用户体验。我们建议每个聊天室的上限人数控制在 5000 人左右。开发者可以考虑从应用层面将大聊天室拆分成多个较小的聊天室。

系统对话(System Conversation)

这是用于实现智能机器人、公众号、服务账号等场景的「对话」,也可以用作发送应用内通知的通道(在 _Conversation 表中,以 systrue 来标记)。这种对话具有以下特点:

  • 加入即订阅,离开即退订,订阅人数没有限制(m 列将被忽略)
  • 系统对话的创建必须由服务端发起,在客户端仅允许订阅/取消订阅一个已经存在的系统对话
  • 可以通过系统对话给所有订阅者发送全局消息,也可以单独某一个或者某几个用户发定向消息
  • 用户给系统对话发送的上行消息是单向的,消息和相关信息会存储在数据存储中的 _SysMessage 表,并不会被其他订阅用户收到
  • 开发者可以配置 Hook 地址接收用户发给系统对话的消息,并利用 REST API 发消息回复

临时对话(Temporary Conversation)

临时对话的数据不会被保存到 _Conversation 表中,它解决的是一种特殊的聊天场景:

  • 对话存续时间短
  • 聊天参与的人数较少(最多为 10 个 Client)
  • 聊天记录的存储不是强需求

这种对话场景,诸如电商售前和售后在线聊天的客服系统,我们推荐使用临时对话。与普通对话相比,它具有如下特点:

  • 不支持消息静音/取消静音的操作
  • 无法更新对话属性
  • 其他消息收发与成员查询操作,和普通对话完全一样

建议:临时对话在使用上与普通对话类似,其最大特点是较短的有效期(不会被保存到 _Conversation 表中),这带来的优势是可以 减轻对话的持久化存储在服务端占用的存储资源规模,从而 降低开发者的使用成本

不同类型的对比总结

对话类型使用场景成员管理收发消息消息记录
普通对话单聊、群聊成员持久化保存,最高支持 500 个成员只有成员可以收发消息支持
聊天室聊天室、弹幕、网页实时评论没有持久化的成员数据,自主加入,不支持邀请,成员数量没有限制所有用户都可以发消息,当前在线的成员可以收到消息支持
系统对话公众号、机器人、下发加好友通知、自定义消息没有成员概念,开发者维护订阅关系,订阅人数没有上限开发者通过 API 给特定用户发消息,支持业务方配置 Web Hook 来备份处理消息支持
临时对话临时客服通道成员固定,无法增加/删除成员只有成员可以收发消息不支持

消息(Message)

即时通讯服务中单次交互的数据单元。用户可以一次传输不超过 5 KB 的消息数据。即时通讯系统对消息格式没有任何要求,允许开发者传输任何基于文本的消息数据,开发者可以在文本协议基础上定义自己的应用层协议。

根据发送参数的不同,消息可分为「普通消息」和「暂态消息」。云端对于普通消息会提供接收回执、自动持久化存储、离线推送等功能。但对暂态消息,则不会被自动保存,也不支持延迟接收,离线用户更不会收到推送通知。譬如聊天过程中「某某正在输入中…」这样的状态信息,就适合按照暂态消息来发送,而用户输入的正式消息,则应该用普通消息来发送。

我们对普通消息提供「至少一次」的到达保证,并且在官方 SDK 中支持对消息的去重,开发者无需关心。开发者可以通过 SDK 或 REST API 发送消息。SDK 通常用于最终用户发送消息,而 REST API 是开发者从云端发送消息的接口。当从 REST API 发送消息时,开发者可以指定消息的发送者、对话 ID,对于系统对话还可以指定消息的接收者。

富媒体消息

为了方便开发者的使用,我们提供了几种封装好的基于 JSON 格式的富媒体消息类型(TypedMessage),譬如:

  • 文本(TextMessage
  • 图片(ImageMessage
  • 音频(AudioMessage
  • 视频(VideoMessage
  • 位置(LocationMessage

这些消息类型的层次关系为:

TypedMessage 继承自 Message。TextMessage、ImageMessage、AudioMessage、VideoMessage、LocationMessage 和其他消息类型继承自 TypedMessage。

富媒体消息基于 JSON 格式,通过 REST API 发送时需要传入符合特定格式的 JSON 字符串。 使用客户端 SDK 发送消息时,SDK 会自动完成相应的转换。

属性约束说明
_lctype富媒体消息的类型
消息类型
文本消息-1
图像消息-2
音频消息-3
视频消息-4
位置消息-5
文件消息-6
以上类型均使用负数,所有正数留给自定义扩展类型使用,0 作为「没有类型」被保留起来。
_lctext富媒体消息的文字说明
_lcattrsJSON 字符串,用来给开发者存储自定义属性。
_lcfile如果是包含了文件(图像、音频、视频、通用文件)的消息 ,_lcfile 就包含了它的文件实体的相关信息。
url文件在上传之后的物理地址(注意,绑定或换绑自定义域名后,历史消息中的 url 不会更新)
objId可选文件服务中对应文件的 objectId
metaData可选文件的元数据

以上为所有类型的富媒体消息共有的属性。

开发者可以基于我们的框架,方便地扩展出自己的消息类型。

与消息相关的其他功能需求

前面章节说明功能特性的时候,我们提到过,在正常收发消息之外我们还支持:

  • 带有提醒功能的 @ 消息(如微信里面的 @ 某人)
  • 消息的撤回和修改
  • 消息内容的实时过滤
  • 消息送达和对方已读的回执通知
  • 群聊里面为了避免过于干扰,允许用户开启消息免打扰开关
  • 发送譬如聊天过程中「某某正在输入…」这样的状态信息
  • 在消息接收方离线时,自动转为推送通知(Push Notification)
  • 对于大型的开放聊天室,为了防止重要消息被淹没或丢弃,支持不同优先级的发送选项,确保重要的消息能优先、迅速送达客户端

具体的使用方法可以参考文档即时通讯开发指南第二篇的《消息收发的更多方式》一节和第三篇的《消息的内容过滤》一节。

系统限制

  • 对于客户端主动发起的操作会按照操作类型限制其频率。发消息操作限制为 每分钟 60 次,历史消息查询操作限制为 每分钟 120 次,其他类型操作包括加入对话、离开对话、登录服务、退出服务等均限制为 每分钟 30 次。当调用超过限制时,云端会拒绝响应这些超限的操作,这样如果操作本由 SDK 发起则表现为不会走回调。如果使用 REST API 发起各种操作,则不会受到上述频率的限制。
  • 应用全局服务器下发消息速度默认最高可达到每秒钟 160000 次,超过部分会被服务器丢弃。如果你的应用会超过此限制,请提交工单联系我们。
  • 客户端发送的单条消息大小不得超过 5 KB(pushData 等附加信息也计入消息大小)。
  • 单个普通对话的成员上限为 500 个,如果你通过数据存储 API 向 m 字段加入了超过 500 个 ID,我们只会使用其中的前 500 个。
  • 请不要使用相同的 ID 在大量设备上同时登录,如果系统检测到某个 ID 同时在超过 5 个不同的 IP 上登录,会认为此 ID 是重复使用的 ID,之后此 ID 当日的每次登录会按照「ID + IP」的组合作为计费的独立用户。
  • 如果单个用户有超过 50 个的对话存在未接收的离线消息,那么当该用户登录时服务端只会 随机 下发 50 个对话的离线消息或未读消息数量。也就是说服务端不会再下发超出对话数量限制的那部分离线消息,也不会下发离线消息数量,离线消息不会丟失但需要从历史记录中拉取得到。
  • 单个对话未接收的离线消息数最多 100 条,超过后,系统会以先入先出方式存储新的离线消息,同时移除当前对话存储的最早的一条离线消息。被移除的离线消息可以通过历史消息记录查询,但不会产生离线消息提醒,也不会计入对话的未读消息计数。
  • 切换文件访问地址(开发者中心 > 你的游戏 > 游戏服务 > 云服务 > 数据存储 > 文件 > 设置)不会自动更新历史消息(包括富媒体消息)中的 URL。
  • 调用消息操作有关的 REST API 有请求频率以及总量的限制,详见即时通讯 REST API

对话的有效期

一个对话(包括普通、暂态、系统对话)如果 6 个月内 没有通过 SDK 或者 REST API 发送过新的消息,或者它在 _Conversation 表中的任意字段没有被更新过,即被视为 不活跃对话,云端会自动将其删除。(查询对话的消息记录并不会更新 _Conversation 表,所以只查询不发送消息的对话仍会被视为不活跃对话。)

不活跃的对话被删除后,当客户端再次通过 SDK 或 REST API 对其发送消息时,会遇到 4401 INVALID_MESSAGING_TARGET 错误,表示该对话已经不存在了。同时,与该对话相关的消息历史也无法获取。

反之,活跃的对话会一直保存在云端。

消息的有效期

一个对话的消息记录会在云端保留 6 个月,也就是说一个对话可以查询到半年之内的历史消息记录。开发者可以付费来延长这一期限,如有需要,请提交工单联系技术支持。 你也随时可以通过 REST API 将聊天记录同步到自己的服务器上。

即时通讯 Hook 机制

详见即时通讯开发指南第四篇的《万能的 Hook 机制》一节。

价格

客户端调用即时通讯服务 SDK,标准版应用按登录用户计费,低于 500 人 / 天 免费,超出部分,则每日 15 元 / 万人

  • 使用 REST API 发送即时通讯消息也是收费的。计费标准就是数据存储 API 调用费用标准(每万次 1.0 元)。此项计费在控制台付费账单明细中对应扣费项目是:「数据存储(API 请求)」。
  • 多媒体消息如果使用到文件服务,正常收取文件费用,文件服务收费标准参考官网价格页面
  • 无论使用 SDK 调用即时通讯服务,还是使用 REST API 调用即时通讯服务,所有访问 _Conversation 表(即会话表)的请求,都会产生数据存储费用。即 _Conversation 表的请求按照数据存储 API 调用标准收费(每万次 1.0 元)。此项计费在控制台付费账单明细中对应扣费项目是:「数据存储(API 请求)」。

开发指南

按功能区分,可以参考如下文档:

具体的 REST API 规范,可以参考: