IM

自研IM平台的技术点解析

浅谈

Posted by LiuShuo on September 22, 2018

最近子弹短信被舆论炒得很火,IM产品似乎又迎来了一个春天,本文主要谈一下IM产品中后端开发涉及到的一些技术点。

IM平台应该具备什么样的功能

IM平台级功能

  • 维护长连接的功能
  • 下行发PUSH的功能
  • 通信通道加密的功能
  • 用户登录token鉴权的功能
  • 保证消息安全存储的功能
  • 对消息本身进行鉴权的功能
  • 历史消息检索的功能
  • 统计和报表相关的功能
  • 审核相关的功能

IM产品基本功能

功能相关

  • 聊天类型需要包括:单聊、群聊以及聊天室(游戏)等
  • 消息载体需要包括:文字、图片、语音、表情、通知和其他自定义扩展消息等
  • 群管理:建群、拉人、踢人、邀请、确认、解散群等
  • 游戏聊天室管理:订阅、退订等
  • 表情相关:自定义表情、表情商店、表情收藏等
  • 分享相关:名片、群二维码、富文本消息转发等
  • 等等

消息相关

  • 消息发送功能,包括普通文本、富文本、多媒体消息和系统消息等
  • 旧消息拉取功能,即向”后”拉取
  • 新消息拉取功能,即向”前”拉取
  • 消息状态同步功能,包括:已发送、已接收、已读
  • @功能,用户名称or本地化别名的展示
  • 消息定位功能,可以跳转到某个特殊位置
  • 消息栅栏功能,栅栏之前的消息不可见
  • 消息撤回功能,如1分钟内可以撤回一发消息
  • 消息删除功能,本地删除不影响对端
  • 消息转发功能,主要是富文本的转发
  • 消息推送和下拉栏推送
  • 等等

会话相关

  • 会话列表拉取功能,涉及各种排序逻辑
  • 会话删除功能,消灭入口
  • 会话提醒功能,如有人@你,有人发红包等
  • 折叠会话功能,类似微信订阅号
  • 等等

IM开发当中的技术难点

IM 开发中的技术难点就在于对用户体验的追求。

首先,IM 核心关注点一是消息传输的速度要快,涉及延时方面的问题;第二个是要保证消息的送达率。同时,现在用户的设备多样化,IM 通常需要支持多设备,又涉及到一个多终端消息同步的问题。

其次,IM 产品的用户量和活跃度通常都很大,在一些特殊的时间点经常容易造成流量的波峰,因此技术上需要能够应对突发的量级。所以在前期需要设计好弹性扩容,对系统的伸缩能力提前做好设计。

最后,IM 包含用户的大量隐私,一旦被黑客攻破不堪设想,同时在公共安全方面的影响也越来越受重视,因此很多 IM 产品都投入精力做内容安全、平台可控方面的工作。

IM通信协议设计的考量

目前行业里有一些开源的方案如 XMPP、MQTT 等。但是,这些开源的方案对后期产品的增长,用户量级的突发式爆增是非常不利的。 原因有几方面,一个是这些开源项目出现的较早,其实并没有考虑到移动互联网 2/3/4G 等复杂的网络情况,包括应对电信运营商在信令等方面的复杂设置,另外,目前鲜有对这些开源技术软件和服务把控度比较强的技术团队,难以进行源码级的扩展和修改,出现问题也难以及时解决。因此,基本上各大IM产品,如QQ、微信等肯定都是自研的协议。

私有协议的优势

私有协议在安全性、带宽节省和可扩展性方面有自己的优势,是开原方案无法比拟的。

  • 安全性方面 可以自己定义加密方式、传输协议、信令种类、序列化方式等。
  • 网络带宽方面 由于用户的网络环境具有非常强的多变性,经常属于跨网和弱网的环境下,所以传输协议非常关注对消息的压缩,以及网络带宽的占用。私有协议可以摈弃Json、XML等臃肿的格式,使用灵活多变的而禁止协议,在网络带宽的节约上有明显效果。
  • 扩展性 私有协议对协议本身的扩展掌握在自己手里,与非传统的协议相比有灵活多变和快速实现等优点。

消息存储和下发方式

推送消息

基于长连接的IM服务的消息大量通过PUSH进行下发,但如果用户设备不在线或网络丢包则无法接收。

缓存消息

服务端为了保证更高的消息拉取性能一般都要把热点数据落入缓存中,保证用户可以快速的拉取最新的若干条记录,而不用去持久层进行查询。服务器需要考虑缓存消息的队列长度以及对应的过期时间等,保证缓存的良性存储率。

持久化消息

光依靠推送和缓存是不够的,消息必须要进行持久化,保证缓存不可用的情况下仍然可以拉取消息,一般都是落入到数据库或HBase中,需要规划好分库、分表规则和RowKey的设计,防止热点数据造成的存储不均。

云端的历史消息

所有消息最终将会落入DW,以提供更长时间范围的消息拉取服务。在用户跨平台或者更换新设备之后,可以随时从云端再获取到这部分的消息,保证消息不会丢失,平台可以借此提供检索等更多的功能。

弹性设计

IM产品的用户量和活跃度通常都很大,在一些特殊的时间点经常容易造成流量的波峰,因此技术上需要能够应对突发的量级。所以在前期需要设计好弹性扩容,对系统的伸缩能力提前做好设计。

动态扩容

包括IM服务器扩容、缓存服务器扩容。

  • IM服务器扩容

IM服务器本身是没有状态的,所以可以灵活的支持横向扩展,如可以通过容器等方式动态增加和减少对应的IM服务器的实例,应对流量洪峰。

  • 缓存服务器扩容

IM服务的实时性要求很高,一般内部都会采用缓存服务器来应对高并发的热数据请求。缓存服务器选型需要考虑是否支持动态扩展、多机房复制和快速恢复等能力,对其鲁棒性有很高的要求。

高峰流控

对非关键路径和数据强一致的场景可以采取熔断和异步化处理。

  • 熔断

如果依赖第三方服务,则需要考虑流量过大时的过载保护问题,如第三方服务可能被流量击垮,在不影响主逻辑的前提下可以使用特殊的“假数据”来处理逻辑,保证服务的可用性。

  • 异步化

在非强一致性要求的场景下可以考虑将数据写到消息队列,由消费者进行异步消费,即和主逻辑完成了解耦避免边界不清,由可以灵活的支持独立部署和服务自治,最终可以达到数据的最终一致性。

IM实时消息监控和分析

IM中的消息在必要的时候需要经过策略风控进行评估,避免不良或非法信息的肆意传播,包括文字、图片等信息,这不但是对建立一个良好的社交环境是一个必备的保障,同时还可以促进对内容运营、内容审核和内容安全运营等方面的建设。

风险控制

考虑到对于不同消息类型进行识别审核的成本(时间、计算能力)的大小,风控类型大致包括:实时风控、异步审核和人工审核三种。

  • 实时风控 在实时发消息的过程中服务器需要同步验证相关信息的合法性,对于平台来说还需要考虑到多APP接入时不同APP的不同风控策略的处理
  • 异步审核 对于实时审核要求高比较影响性能的场景或者对实时风控的一种额外保证,此时可能消息已经投递出去,需要提供对非法消息的撤回(删除)功能,提供事后保障机制,避免二次传播
  • 人工审核 在必要的情况下所有合法数据仍然需要通过人工进行再次审核保证机器学习算法的错误率不会造成较大的影响

内容保存

平台需要具备内容审核的能力,所以平台上产生的内容需要安全的保存起来,以备监管层随时做内容的审核。

如何保证消息安全性

通信安全

即消息传输层面的安全,在传输过程中,通过协议和加密算法进行保证,使传输过程中的消息是不可逆的。恶意用户即使抓到网络传输的包也没有办法破译出来。

会话安全

加密级别最好做到会话级别,即一个用户的一次长链接中使用固定的密钥,即使同一个用户多次登录,或者在不同时间点登录,加密的密钥都是不一样的。

数据存储安全

这里主要涉及:

  • 如何实现数据的高效存储和访问 涉及到序列化和反序列化的算法和数据结构
  • 如何实现尽量小的存储空间 可以考虑配合一定的压缩算法进一步减少序列化后的数据的大小
  • 数据的加密存储 需要有统一的密钥管理体系来保证数据的加密存储以及密钥的安全性,保证被拖库后数据仍然是安全的

数据脱敏

一般的IM中的用户账号体系都是采用自增ID来设计的,这样的坏处是可以被猜测已经容易受到攻击。 可以通过在业务层做一个mapping来避免暴露用户的核心信息,如uid、手机号等。具体算法可以使用混淆算法或自定义混淆数据库里的数据做映射,一般都是使用无法猜测的定长字符串的形式生成映射库里的数据。

防止重放

数据在整个传输的过程中可能存在安全风险,比方第三方的攻击,以及数据在网络流转过程中被拷贝和重放的潜在安全风险,这些在设计过程中都需要被规避掉。

参考

  • https://mp.weixin.qq.com/s/s5PG4FhHy38sJH4tsMv9WA

本文首次发布于 LiuShuo’s Blog, 转载请保留原文链接.