IM 客户端技术演进路线(上)

简介: IM 客户端技术演进路线(上)

IM 技术演进阶段


IM v1.0 阶段(简单、可用)



image.png


实现功能


  • 用户/客服接入
  • 消息收发
  • 咨询列表管理


设计原理


  • 通过「消息转发模块」中消息轮询协程操作 Redis 缓存进行消息分发
  • 使用 Protobuf 解决数据传输问题
  • 使用 Java NIO 的开源框架 Netty 异步非阻塞、事件驱动、高性能、高可靠、高可定制性的网络应用程序


技术选型


  • (v1.0 选型)基于 Scoket 原生:代表框架 CocoaAsyncSocket
  • (v2.0 选型)基于 WebScoket :代表框架 SocketRocket
  • 基于 MQTT:代表框架 MQTTKit
  • 基于 XMPP:代表框架 XMPPFramework


两种方案设计

  • 集中式:简单的单通、双通,延迟率要求不高的消息发送。
  • 分布式:实时的双通、多通,延迟率高要求的视频/语音通话。


问题


FAQ:TCP 选型,实现通讯信息的真正加密,复杂场景下更灵活的通信。


问题 1:分/黏包

  • 分包(IP分片传输导致):指接受方没有接受到一个完整的包,只接受了部分。
  • 黏包(TCP协议本身合并机制):指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看,后一包数据的头紧接着前一包数据的尾。

解决:

  • 方案一:包头长度字段
  • 方案二:包尾分隔标识

应用:消息头长度为2个字节,所以消息包的最大长度需要小于65536个字节,netty会把消息内容长度存放消息头的字段里,接收方可以根据消息头的字段拿到此条消息总长度。


问题 2:数据丢失

  • 数据丢失,写 db 之前 App crash,虽然数据在网络层可靠抵达了,但没存进 db,下次用户打开 App 消息自然就丢失了,如果不在业务层再增加可靠性保障,网络层面不会重发,那么意味着这条消息对于 Receiver 永远丢失

解决:

  • 方案一:应用层 Ack 消息(消息回调机制)
  • 方案二:应用层 Seq ID(连续性编号)


IM v2.0 阶段


image.png


开发要求


  • 提升服务业务功能
  • 增加可选配置,例如自动回复、FAQ


发展历程


  • 第一阶段:短轮询 Polling(频繁的异步 JavaScript 和 XML (AJAX) 请求来实现轮循)
  • 第二阶段:长轮询 Long polling(由服务端决定回执的长轮询机制)
  • 第三阶段:基于 AJAX、Flash Socket 等流实现
  • 第四阶段:WebSocket HTTP 5.0 全双工


区别整理

  • WebSocket 是应用层的协议,Socket 是传输层的抽象
  • WebSocket 是全双工的 HTTP 通讯协议


设计原理


  • 建立一条可复用、可检索的消息线路(通过 HTTP 协议进行一个握手的动作,然后单独建立一条 TCP 的通信通道进行数据的传送)
  • 分配服务优化:平均、权重、排队、AI
  • 消息服务配置:风险检测、离线存储、消息队列、更新未读数、自动回复


保障性机制


  • 方案一:应用层 Ack (确认字符) 消息
  • 方案二:应用层 Seq ID(每个 Message 分配一个 Seq ID,这个 Seq ID 对于单个用户的接受消息队列来说是连续的)


心跳机制

定时心跳包

每隔若干时间发送一个固定信息给服务端,服务端收到后及时回复一个固定信息,如果服务端若干时间内没有收到客户端心跳信息则视客户端断开,同理如果客户端若干时间没有收到服务端心跳回值则视服务端断开。 ① 前台时,8秒发送一个心跳包; ② 切换到后台时,30秒发送一次,根据自己的实际情况修改一下即可。心跳包用于维持长连接以及检测长连接是否断开等。


智能心跳包

1)App 前台时:五次延迟测试确定网络情况良好,进入长心跳模式;在网络波动较大的情况,使用短心跳,保证收取消息相对及时。 2)App 后台时:先用几次最小心跳维持长链接,进入后台自适应心跳计算。(尽量选择用户不活跃的时间段,来减少心跳计算可能产生的消息不及时收取影响。)


重连流程

  • 重连被触发时,如果该次连接成功,退出重连
  • 反之重连失败后,会判断当前重连的次数是否超过预期值(这里设为6次),并对重连次数计数,如果超过就会退出重连
  • 休眠预设的时间后再次进行重连操作


重连触发条件分为三种:

  • 主动连接不成功(主动连接Socket,如果连接失败,会触发重连机制)
  • 网络被主动断开(正常建立连接,操作过程中,网络被断开,通过系统广播触发重连)
  • 服务器没响应,心跳没回值(服务端心跳预设时间内没回值,客户端认为服务端已经断开,触发重连)


发送消息类别

  • 一类是 IM 相关数据的请求(HTTP),例如:历史消息列表,会话列表等
  • 二类是 IM 消息的发送(Socket),主要是文字消息,包括上传到服务器的资源文件链接等
  • 三类是辅助通信类型(混合),一般封装进 SDK 内部,例如:心跳包、回执、鉴权等


对应后端 API 设计:2.1 保活心跳包(C->S) HeartbeatPackage【13】 2.2 响应心跳包(S->C) XXX【??】 2.3 探查客户端是否活跃(S->C) XXX【??】 2.4 拉取离线消息(C->S) ClientRequestMessage【13】 2.5 响应离线消息(S->C) Protobuf【22】 2.6 发送聊天消息(C->S) ChatMessage【10】 2.7 响应发聊天消息(S->C) Protobuf【29】 2.8 接收聊天通知(S->C) ChatMessage【10】 2.9 接收代办通知(S->C) TodoMessage【17】 2.10 漫游和搜索聊天历史(C->S) ClientRequestMessage【13】 2.11 响应漫游和搜索聊天历史(S->C) Protobuf【30】 2.12 获取好友列表(C->S) ClientRequestMessage【13】 2.13 响应好友列表(S->C) Protobuf【18】 2.14 获取圈子列表(C->S) ClientRequestMessage【13】 2.15 响应圈子列表(S->C) Protobuf【20】 2.16 获取代办列表(C->S) ClientRequestMessage【13】 2.17 响应代办列表(S->C) Protobuf【23】


业务缓存策略

(先查数据库后展示,没有再请求再显示)

1)首次会话:先查数据库 -> 显示UI -> 网络请求 -> 算出未读数据存入数据库 -> 显示UI 2)拉取历史数据:先查本地数据 -> 根据字段 msgid 是否为 0 请求数据并存储 -> 显示UI 3)单条消息发送:发送信息 -> 标记为插入失败 -> 插入数据库 -> 发送信息(成功接收回执:变为成功状态存储,发送失败或没有接收到回执:进入重发流程)-> 显示UI


IM v3.0 阶段


实现功能(服务拆分)

  • 业务服务:客服群组/成员管理、搜索服务、质检服务、工单服务、优惠券、订单服务、自动回复、FAQ
  • 用户服务:用户状态、行为轨迹(画像)、评价服务
  • IM 服务:单聊、群聊、通知、私信、联系人、文件服务、风控服务、敏感词过滤
  • 数据服务:采集、分析、统计


功能模块主要分为(现代 IM 系统中的消息系统架构——实现篇:www.infoq.cn/article/N6s…

  • 消息存储:读、写、持久化,单行写入,批量读取,多维检索、全文检索的模糊查询
  • 关系维护:人与人的关系、人与群的关系以及人与会话的关系
  • 即时感知:会话池方案,消息存储 > 第二类:同步库 > 新消息即时统计
  • 多端同步:会话的未读消息数需要在应用服务侧维护、对自己的信息不计数在最新消息摘要中需要做更新


分页设计

  • 规则:从数据库拉取
  • 首次:sequenceId 范围 + 倒序
  • 翻页:第一次请求的最小 sequencId 发起第二次请求


需求分析


  1. 可能在有些需求中,消息还会区分平台,比如ios/andoid/mac/windos等
  2. 关于信息的更新:某一个人的个人头像or昵称发生了变化,这时候,我们对应的消息页面的UI,朋友列表等需要更新。这种类型的通知,一般是通过tcp推送,后台通过查找该用户的uid然后查找到他的会话跟好友列表然后进行推送。
  3. 关于消息的设计:目前我所见是2种,一种是类型微信的常见,具有离线消息的概念,但是一旦客户端确认接收到,服务器将不会保存,也就是不能跨设备保存用户记录,一般用tcp实现。还有一种是类似钉钉那种,有一个同步消息的概念,这种情况下一般使用Tcp+Http实现。他们的逻辑相差还是比较大,会另外写一篇文章描述。


目录
相关文章
|
20天前
|
资源调度 JavaScript 前端开发
IM跨平台技术学习(十一):环信基于Electron打包Web IM桌面端的技术实践
这次借着论证 Web IM端 SDK 是否可以在 Electron 生成的桌面端正常稳定使用,我决定把官方新推出的 webim-vue3-demo,打包到桌面端,并记录了这次验证的过程以及所遇到的问题和解决方法。
30 2
|
27天前
|
机器学习/深度学习 存储 人工智能
构建基于AI的智能客服系统的技术探索
【6月更文挑战第6天】本文探讨了构建基于AI的智能客服系统,强调其在快速、准确、个性化响应客户方面的重要性。系统关键技术包括自然语言处理(NLP)、知识库管理、自主学习和更新以及多渠道支持。NLP使用深度学习模型理解用户输入,知识库存储解决方案,自主学习通过反馈和新数据优化性能。智能客服系统能提供高效、准确、个性化的服务,并具有良好的可扩展性,未来将在更多领域发挥作用。
|
2月前
|
移动开发 网络协议 Java
即时通讯技术文集(第38期):IM代码入门实践(Part2) [共15篇]
为了更好地分类阅读 52im.net 总计1000多篇精编文章,我将在每周三推送新的一期技术文集,本次是第38 期。
48 1
|
2月前
|
安全 Java 数据库
即时通讯技术文集(第37期):IM代码入门实践(Part1) [共16篇]
为了更好地分类阅读 52im.net 总计1000多篇精编文章,我将在每周三推送新的一期技术文集,本次是第37 期。
39 2
|
2月前
|
存储 缓存 算法
IM技术干货:假如你来设计微信的群聊,你该怎么设计?
微信背后的这个IM群聊系统到底是如何实现的呢?这个问题一直困扰着,于是我决定深入了解一下,看看微信的群聊系统背后的设计是怎样的。
56 1
|
2月前
|
存储 Java 应用服务中间件
即时通讯技术文集(第36期):《跟着源码学IM》系列专题 [共12篇]
为了更好地分类阅读 52im.net 总计1000多篇精编文章,我将在每周三推送新的一期技术文集,本次是第36期。
37 0
|
2月前
|
缓存 架构师
即时通讯技术文集(第35期):IM群聊技术合集(Part2) [共12篇]
为了更好地分类阅读 52im.net 总计1000多篇精编文章,我将在每周三推送新的一期技术文集,本次是第35 期。
48 1
|
2月前
|
机器学习/深度学习 自然语言处理
基于深度学习的自然语言处理技术在智能客服系统中的应用
【2月更文挑战第21天】随着人工智能技术的不断发展,自然语言处理(NLP)技术在各个领域得到了广泛应用。本文主要探讨了基于深度学习的自然语言处理技术在智能客服系统中的应用。首先介绍了深度学习和自然语言处理的基本概念,然后分析了智能客服系统的工作原理和技术要求,接着详细阐述了基于深度学习的自然语言处理技术在智能客服系统中的具体应用,包括语义理解、情感分析和问答系统等。最后对基于深度学习的自然语言处理技术在智能客服系统中的优势和挑战进行了总结。
179 1
|
2月前
|
人工智能 自然语言处理 搜索推荐
AIGC: 2 语音转换新纪元-Whisper技术在全球客服领域的创新运用
全球客服领域的发展设想结合点: 1.智能客服语音助手: 2.多语言无缝服务体验: 3.语音分析与情感智能
881 2
|
2月前
|
存储 NoSQL Redis
陌陌技术分享:陌陌IM在后端KV缓存架构上的技术实践
在本文中,陌陌数据库负责人冀浩东将聚焦探讨陌陌的 KV 系统架构选型思路,深入解析如何进行此类系统的甄选决策,同时进一步分享陌陌团队在采用 OceanBase(OBKV)过程中所经历的探索与实践经验。
64 0