Code-Life icon indicating copy to clipboard operation
Code-Life copied to clipboard

IM 架构

Open Draymonders opened this issue 3 years ago • 3 comments

跟着 @hanggegreat 一起学习 && 实战 简单的IM

Draymonders avatar Oct 24 '20 02:10 Draymonders

跟着 @hanggegreat 一起学习 && 实战 简单的IM

饼爷yyds

hanggegreat avatar Oct 24 '20 02:10 hanggegreat

基础篇

完整的IM的需求

  • 实时性
  • 可靠性 (不重复,不丢)
  • 一致性 (消息有序,多终端同步消息一致)
  • 安全性

消息收发架构

消息存储在哪里

  • 为方便检索,store at client。
  • 未读消息,多端信息同步,store at server

消息存储及索引

  • 消息存储需要 message_id, from_user_id, to_user_id, message, message_type, timestamp
  • 消息索引需要 from_user_id, to_user_id, message_id

消息发送与接收

send client -> IM server -> receive client

未读

  • 某人的总未读数
  • 某人和另外一个人的会话未读数

实时性

  • 短轮询
  • 长轮询
  • 边缘触发(状态发生改变,产生io事件
    • websocket

可靠性

  • 大部分场景和实际实现中,通过业务层的 ACK 确认和重传机制,能解决大部分推送过程中消息丢失的情况。
  • 通过客户端的去重机制,屏蔽掉重传过程中可能导致消息重复的问题,从而不影响用户体验。
  • 针对重传消息不可达的特殊场景,我们还可以通过“兜底”的完整性检查机制来及时发现消息丢失的情况并进行补推修复,消息完整性检查可以通过时间戳比对,或者全局自增序列等方式来实现。

一致性

  • 分布式自增id, 需要保证群组内的消息一致性, 可以先按照groupid hash到一台发号器,然后利用snowflake算法去生成有序的id
  • 服务端多个tcp包合并,按照业务id进行排序再推送
  • 接收端也需要根据业务id进行排序然后展示
  • 全局自增id会存在单点性能问题

安全性

  • 端到端的加密
  • 内容安全(文字,语音,图片校验)

事务

  • 分布式事务(保证多个操作的原子性)
  • 分布式锁(依赖redis or zk 数据库,存在单点瓶颈,影响吞吐)

心跳

心跳解决了以后三方面问题

  • 降低服务端无效链接的开销
  • 支持客户端快速识别无效链接,自动断线重连
  • 链接保活,便面被运营商NAT超时断开

心跳探测方式

  • TCP keepalive
  • 应用层心跳

Draymonders avatar Oct 24 '20 05:10 Draymonders

场景篇

多终端消息漫游

  • 在线
    • 服务端对用户所有的设备维护状态,然后将一条消息推送到所有设备
  • 离线
    • 设备在线后,再推送离线消息(有offset)

峰值流量的应对

  • 在线状态本地化维护,降低远程资源依赖,提升单机处理能力。
  • 对服务整体进行拆分,区分核心和非核心服务,隔离“容易出现瓶颈”的服务。
  • 通过收集业务和机器两类指标,建立容量评估模型,自动进行服务扩缩容。
  • 根据后端机器负载水平调度全局,接入服务入口,解决扩容后新接入流量在新扩容机器和旧机器间流量不均衡的问题。
  • 对于长连接的网关服务(有状态),我们缩容是只需要禁止新的建连请求接入,已存在的长连接尽量等用户自动断开后关闭,对于剩余的少量的长连接可以采取强制断开方式,等待客户端断连重连即可。

Draymonders avatar Oct 25 '20 08:10 Draymonders