转转客服IM聊天系统背后的技术挑战和实践分享

本文由转转技术李帅的原创分享,已进行修订和排版优化。

1、引言

在当今互联网时代,高效的用户服务是提升用户体验的关键。转转自研的客服IM聊天系统作为用户与客服沟通的桥梁,承担着传递信息、解决问题的关键角色。然而,消息数据的流转并非一帆风顺,本文将深入探讨IM系统在消息传递过程中遇到的问题和挑战,以及相应的技术解决方案。

如图是IM系统中一条消息的流转链路:

 

1

相较于普通web系统,IM系统的消息数据流转链路更长、更复杂。从客户端到服务端,再从服务端到另一个客户端,任何一个环节的故障都可能导致消息延迟、丢失、乱序或重复,从而影响用户体验。

网络波动和客户端设备性能的不稳定性是影响IM系统性能的主要因素,这些因素可能导致消息的实时性、可靠性和完整性受到威胁。

技术交流:

- 移动端IM开发入门文章:《新手入门一篇就够:从零开发移动端IM》

- 开源IM框架源码:https://github.com/JackJiang2011/MobileIMSDK(备用地址点此)

(本文已同步发布于:http://www.52im.net/thread-4874-1-1.html)

2、关于作者

李帅:转转履约中台研发工程师,主要负责客服工单、IM等系统研发。

3、如何保证聊天消息的实时性

首当其冲的就是消息延迟问题:当一条消息发出后,我们的系统需要确保这条消息最快被接收人感知并获取到,并且保证资源消耗较少。

这里关键的点是:

  • 1)最快触达;
  • 2)耗费资源少。

方案1:长短轮询

在PC web早期,大部分应用都是采用“一问一答”的请求响应模式来获取数据,IM系统采用客户端轮询的方式,定期、高频轮询获取服务端的新消息。这种方式开发成本较低、容易实现,但是高频轮询很多请求是无用请求,客户端浪费流量和电量,服务端资源压力很大。

后来基于短轮询进化出长轮询模式,相较于前者,后者在请求时获取到新数据时不会立即返回,而是在服务端保持连接等待一段时间,如果等待期间有新消息就立即返回响应,长轮询仅仅解决了客户端的无用消耗,但是服务端资源高负载情况依然未能解决。

方案2:WebSocket

随着HTML5的出现,全双工的WebSocket成为解决这一问题的关键。基于WebSocket实现的IM服务,客户端和服务端只需要完成一次握手,就可以创建持久的长连接,并进行随时的双向数据传输。

2


经过比较转转客服IM系统采用了WebSocket协议,具体使用方式见《转转客服IM系统的WebSocket集群架构设计和部署方案》。当服务端接收到新消息时,可以通过建立的WebSocket连接,直接进行推送,保证了消息到达的实时性。

关于传统Web和现代Web的实时通信技术,可详读以下几篇:

  1. Web端即时通讯技术盘点:短轮询、Comet、Websocket、SSE
  2. 详解Web端通信方式的演进:从Ajax、JSONP 到 SSE、Websocket
  3. 网页端IM通信技术快速入门:短轮询、长轮询、SSE、WebSocket

4、什么是聊天消息的可靠性

如图是一条消息发送的核心步骤,整个过程中可以分为两个部分,消息由客户端发送到服务端(第1、2步),服务端将消息推送至另一个客户端(第3步),发送过程中任何一步出现问题都会导致消息发送失败。

3

PS:限于篇幅原因,本文不想深入探讨,有兴趣可详读《零基础IM开发入门(三):什么是IM系统的可靠性?》。

5、如何保证聊天消息触必达?

我们参考使用了TCP/IP协议中的ACK机制来实现防丢逻辑(《TCP/IP详解 - 第17章·TCP:传输控制协议》)。ACK机制是TCP/IP协议三次握手重要的一环(请详读《脑残式网络编程入门(一):跟着动画来学TCP三次握手和四次挥手》),用于确认对方发送信息无误。

ACK响应机制如下:

  • 1)发送者发送消息时会携带一个消息标识符(此处使用发送方id和消息发送时间戳)、并在本地维护一个“等待ACK消息列表”;
  • 2)接收者收到消息后对消息进行存储得到消息id;
  • 3)随后再将该标识回传给发送方(ACK消息);
  • 4)发送方收到ACK消息后将消息从“等待ACK消息列表”删除;
  • 5)当发送方没有在约定时间内收到ACK消息时,就需要执行失败消息处理逻辑:自动重发、客户端标记发送失败等。

服务端实现与客户端稍有不同,服务端需要要维护全量用户的消息,使用定时任务检查等待ACK消息列表效率比较低,此处通过mq的延迟消息来实现:

当消息发出时同时发送一个延迟mq,延迟消息被消费时对应的消息仍在等待ACK列表中,则表示消息未能在规定时间内被确认,需要进行重试发送。

如图为完整的ACK实现机制:

4

另外客户端也会在页面刷新、WebSocket重连时触发http接口重新拉取当前会话的所有消息进行渲染,保证消息不丢失。

PS:相关资料可进一步阅读:

  1. IM消息送达保证机制实现(一):保证在线实时消息的可靠投递
  2. 阿里IM技术分享(四):闲鱼亿级IM消息系统的可靠投递优化实践
  3. 融云技术分享:全面揭秘亿级IM消息的可靠投递机制
  4. 一套亿级用户的IM架构技术干货(下篇):可靠性、有序性、弱网优化等

6、如何对聊天消息去重?

消息重推解决了消息丢失的问题,但是因为ACK消息本身就可能会丢失从而导致消息重复,因此我们需要保证推送消息和重推消息有相同且唯一的消息id,接收方可以根据该消息id进行数据去重。

具体是:

  • 1)发送方:客户端使用发送人id和消息发送时间戳作为唯一的ACK标识,传递给服务端;
  • 2)服务端:使用雪花算法接收到的消息生成消息id,将ACK标识与消息id建立映射关系;服务端再将消息id推送至发送方和接收方。

一个完整的消息发送流程如图所示:

5

7、心跳保活机制

IM系统中接收和发送消息都是使用长连接实现,但是如果连接断开,那发送和接收数据就会出现问题。在客服业务中,人工客服席位有限,系统需要可靠的机制保证人工客服资源有效利用。

为此我们在应用层设计心跳消息,使用该机制更新用户当前状态、保证会话有序退出。

心跳机制设计如下。

客户端:设置定时器,用户建立连接后,定时发送(30s)心跳消息给服务端。

服务端:

  • 1)接收心跳消息,更新心跳时间;
  • 2)设置定时任务,定时扫描在线用户上次心跳时间,执行以下逻辑;
  • 3)上次心跳时间超出30s,将其标记为离线状态,关闭连接,等待用户重连;
  • 4)上次心跳时间超出2分钟则认为用户已经彻底离开,执行会话关闭逻辑释放人工客服资源。

应用层心跳消息仅用于保活和状态更新,因此数据结构设计十分精简,不携带额外信息。

关于心跳保活这方面的资料,可以进一步阅读:

  1. 为何基于TCP协议的移动端IM仍然需要心跳保活机制?
  2. 一文读懂即时通讯应用中的网络心跳包机制:作用、原理、实现思路等
  3. 微信团队原创分享:Android版微信后台保活实战分享(网络保活篇)
  4. 融云技术分享:融云安卓端IM产品的网络链路保活技术实践
  5. 跟着源码学IM(五):正确理解IM长连接、心跳及重连机制,并动手实现
  6. 阿里IM技术分享(五):闲鱼亿级IM消息系统的及时性优化实践
  7. 万字长文:手把手教你实现一套高效的IM长连接自适应心跳保活机制

8、消息协议的设计

在IM系统中消息格式的设计也十分重要,良好的数据格式可以准确传递消息内容并具有极高的可读性。

我们根据消息类型和发送流向将消息数据格式大致分为如下几部分:

  • 1)消息类型:用于描述消息的用途、流向,如心跳消息、用户/客服消息、系统消息等;
  • 2)客服id:接收或者发送消息的客服标识;
  • 3)用户id:接收或者发送消息的用户标识;
  • 4)消息内容:实际的消息,与消息类型相关;
  • 5)消息格式:用于描述用户/客服消息格式,如文本、图片、视频、订单卡片、优惠券等;
  • 6)消息文本:消息的展示内容。

6

PS:IM协议设计相关资料可进一步阅读:

  1. 简述移动端IM开发的那些坑:架构设计、通信协议和客户端
  2. 理论联系实际:一套典型的IM通信协议设计详解
  3. APP与后台通信数据格式的演进:从文本协议到二进制协议
  4. IM通讯协议专题学习(一):Protobuf从入门到精通,一篇就够!

9、本文小结

转转客服IM系统通过引入WebSocket协议、ACK机制、消息重推和数据去重等策略,有效应保障了消息传递过程中的实时性、可靠性和完整性。这些技术的应用,不仅提升了用户与客服之间的沟通效率,也为转转平台提供了更加稳定、高效的服务支持。

在未来的发展中,我们将继续优化和完善,以应对不断变化的需求和用户期望,为用户提供更加优质的服务体验。

10、参考资料

[0] TCP/IP详解 - 第17章·TCP:传输控制协议》

[1] Web端即时通讯技术盘点:短轮询、Comet、Websocket、SSE

[2] 详解Web端通信方式的演进:从Ajax、JSONP 到 SSE、Websocket

[3] 网页端IM通信技术快速入门:短轮询、长轮询、SSE、WebSocket

[4] Web端即时通讯实践干货:如何让你的WebSocket断网重连更快速?

[5] 简述移动端IM开发的那些坑:架构设计、通信协议和客户端

[6] IM消息送达保证机制实现(一):保证在线实时消息的可靠投递

[7] 阿里IM技术分享(四):闲鱼亿级IM消息系统的可靠投递优化实践

[8] 阿里IM技术分享(五):闲鱼亿级IM消息系统的及时性优化实践

[9] 融云技术分享:全面揭秘亿级IM消息的可靠投递机制

[10] 一套亿级用户的IM架构技术干货(下篇):可靠性、有序性、弱网优化等

[11] 理解IM消息“可靠性”和“一致性”问题,以及解决方案探讨

[12] 微信团队分享:来看看微信十年前的IM消息收发架构,你做到了吗

[13] 阿里IM技术分享(七):闲鱼IM的在线、离线聊天数据同步机制优化实践

[14] IM群聊消息如此复杂,如何保证不丢不重?

[15] 开发IM是自己设计协议用字节流好还是字符流好?

[16] 零基础IM开发入门(一):什么是IM系统?

[17] 零基础IM开发入门(二):什么是IM系统的实时性?

[18] 零基础IM开发入门(三):什么是IM系统的可靠性?

[19] 零基础IM开发入门(四):什么是IM系统的消息时序一致性?

[20] 脑残式网络编程入门(一):跟着动画来学TCP三次握手和四次挥手

(本文已同步发布于:http://www.52im.net/thread-4874-1-1.html)

相关推荐

鸿蒙原生即时通讯/IM系统RainbowTalk v2.8版发布,基于MobileIMSDK框架、ArkTS编写

💧 此版本解决了若干bug,以及ui和功能细节优化,同时支持最新鸿蒙7.0系统。

hellojackjiang2011的博客 165

深度剖析IM消息乱序的根本原因及优化方法

本文深度剖析即时通讯IM消息乱序的问题,梳理IM客户端时间戳不可信、多端并发、群消息扇出重试三大核心陷阱,拆解微信、钉钉、企业微信的时序设计方案,并从锚点设计、多端去交错、幂等兜底、可观测性等维度,给出IM项目消息时序性保证的落地优化策略。

hellojackjiang2011的博客 293

IM聊天不掉线?生产级WebSocket断线重连、心跳保活实战

本文将给出一套生产级Web端即时通信方案,包括心跳检测保活 + 指数退避重连,代码直接能跑。

hellojackjiang2011的博客 319

IM全文检索技术(五):vivo敏感词匹配系统的技术实践

本文将从算法选型入手,结合两个实际场景来介绍谛听系统的敏感词匹配算法。包括底层算法选型思路和两种实际场景下提升敏感词精准度、降低漏杀率的方案。

hellojackjiang2011的博客 189

Nginx生产级WebSocket实时长连接负载均衡,一文搞定

本文从基础配置、生产配置、Docker / K8s、安全、排障、性能调优,系统性讲清 WebSocket 在 Nginx 中的正确打开方式。

hellojackjiang2011的博客 308

即时通讯IM离线消息该怎么存?全面盘点主流存储方案

离线消息是IM系统的核心能力,当用户不在线时,消息必须可靠存储,待用户上线后完整推送。本文将对比主流的离线消息存储方案,帮你找到最适合业务场景的架构。

hellojackjiang2011的博客 310

移动端实时音视频聊天框架 RainbowAV v2.2.7发布

1)

hellojackjiang2011的博客 247

都HTML5了,Web端即时通讯技术到底该用什么?一文即懂!

本文分享的是 Web 端最常用即时通讯技术(包括 WebSocket、SSE、WebRTC、轮询等)的原理、优缺点与适用场景等,以及生产环境下的高并发场景下的进阶实践。

hellojackjiang2011的博客 341

基于开源MobileIMSDK框架,即时通讯IM产品RainbowChat v12.1发布

此版本新增了短信验证码的注册和登录功能,解决了Android 16手机上发送文件失败等问题。

hellojackjiang2011的博客 209

IM千人群聊该不该用消息写扩散?详细算算成本账!

本文将为你详解 IM 群聊消息的写扩散技术原理以及写扩散过程中的服务端详细性能成本,同时对比了市面上IM大厂的技术方案,给出分规模架构选型与以及性能优化策略等。

hellojackjiang2011的博客 402

直播系统聊天技术(十):基于实时消息总线的活动系统架构设计

本文分享的是网易云音乐技术团队基于实时消息总线技术,解决了直播活动系统的模块灵活组合、消息治理与异步履约等问题,希望能给你带来启发。

hellojackjiang2011的博客 369

轻量级Web端IM即时通讯框架MobileIMSDK-Web,基于Socket.io库

MobileIMSDK-Web是一套Web端即时通讯框架,超轻量级、极少依赖,高度提炼、简单易用。

hellojackjiang2011的博客 286

socket长连接在手游场景下的技术实践

本文介绍了37手游基于B站goim框架自研长连接系统的实践。系统采用分层设计,支持多协议和发布/订阅机制,用于直播弹幕、实时推送等场景,实现了高性能与业务适配。

hellojackjiang2011的博客 404

基于开源MobileIMSDK框架,即时通讯IM产品RainbowChat v12.0发布

RainbowChat 是一套基于 MobileIMSDK 开源通信框架的产品级移动端IM系统。可能是市面上开放源码的,唯一一款同时支持TCP、UDP、WebSocket三种网络通信协议的IM产品。

hellojackjiang2011的博客 518

社交场景下的统一即时通讯im消息流交互层模块化技术实践

这些IM场景,在消息流的展示形式上是极为相似的,同时每个业务又有着自己特殊的交互需求。基于此,我们对IM消息流能力做了标准化的构建,来减少IM功能的业务接入成本;同时也是为了统一各个业务的技术方案,减少跨业务开发的理解和维护成本。

hellojackjiang2011的博客 571

现代IM系统中聊天消息的同步和存储方案探讨

本文内容主要涉及IM系统中的消息系统架构,探讨一种适用于大用户量的消息同步以及存储系统的架构实现,能够支持消息系统中的高级特性“多端同步”以及“消息漫游”。在性能和规模上,能够做到全量消息云端存储,百万TPS以及毫秒级延迟的消息同步能力。

hellojackjiang2011的博客 75

即时通讯安全篇(十六):对称加密 vs 非对称加密?一文搞懂

本文将以通俗案例讲解加密本质,介绍对称加密(含 AES、迪菲–赫尔曼密钥交换)与非对称加密(RSA)原理、特点及应用,并阐释其数学基础。

hellojackjiang2011的博客 397

网络编程入门如此简单(五):UDP跟TCP相比,到底差了什么?

本文将通俗易懂地为你类比解释UDP与TCP的核心差异,包括如何基于UDP实现TCP的可靠传输:通过模拟三次握手、添加序列号与确认机制解决顺序和丢包问题,利用滑动窗口控制流量,并引入拥塞控制算法来动态调整发送速率等。

hellojackjiang2011的博客 448

基于WebSocket的IM即时通信方案在H5游戏场景下的技术实践

本文将从H5游戏场景下的实时信息更新需求切入,探讨下在类似这种高并发、低延迟的业务需求中,如何使用 IM 方案来解决频繁的数据更新问题,也顺便介绍下 WebSocket 的基本运作流程等。

hellojackjiang2011的博客 1069

鸿蒙Next原生IM即时通讯RainbowTalk,纯ArkTS编写,基于开源MobileIMSDK框架

RainbowTalk 是一套基于 MobileIMSDK 开源通信框架的产品级纯血鸿蒙NEXT端IM系统。RainbowTalk 由纯ArkTS编写、全新开发,没有套壳、也没走捷径,原生“纯血”。

hellojackjiang2011的博客 1229

如何保障分布式IM聊天系统的消息可靠性(即消息不丢)

本文主要聚焦分布式IM聊天系统消息可靠性问题,即如何保证消息不丢失。

hellojackjiang2011的博客 732

如何保障分布式IM聊天系统的消息有序性(即消息不乱)

本篇主要总结和分享分布式IM聊天系统架构中关于消息有序性的设计和实践。

hellojackjiang2011的博客 835

B站即时通讯IM消息系统的新架构升级实践

本文要分享的是B站IM消息系统的新架构升级实践总结,内容包括原架构的问题分析,新架构的整体设计以及具体的升级实现等。

hellojackjiang2011的博客 714

AI大模型爆火的SSE技术到底是什么?万字长文,一篇读懂SSE!

本文从SSE(Server-Sent Events)技术的原理到示例代码,为你通俗易懂的讲解SSE技术的方方面面。

hellojackjiang2011的博客 786

腾讯新闻APP的消息推送Push架构技术重构实践

本文主要分享的是腾讯技术团队近年来对腾讯新闻消息推送PUSH系统做的架构优化和技术实践。

hellojackjiang2011的博客 843

移动端弱网优化专题(十五):字节跳动移动端网络HttpDNS优化实践

本文要分享的是字节跳动团队针对火山HTTPDNS Cache2.0通过自研网段库与动态划分算法,将缓存粒度从“城市-运营商”细化为“网段”,解决了传统方案的城市级调度污染问题。配合缓存分级、预取等优化,在提升调度精准度的同时保证了高命中率,最终实现了服务端调度准确性提升和客户端性能优化。

hellojackjiang2011的博客 720

ChatGPT如何实现聊天一样的实时交互?快速读懂SSE实时“推”技术

本文将带你快速认识SSE实时通信协议,包括它的技术原理、常见使用场景、与同类技术的对比以及简单的示例代码等。

hellojackjiang2011的博客 124

全面适配iOS 26液态玻璃,基于开源IM即时通讯框架MobileIMSDK:RainbowChat-iOS端v10.2发布

RainbowChat是一套基于开源IM即时通讯聊天框架 MobileIMSDK 的产品级移动端IM系统。

hellojackjiang2011的博客 1157

可靠传输的TCP协议send成功就意味着数据一定发出去了?

本篇文章我们以TCP协议的网络编程逻辑,从Socket缓冲区的角度去拆解,为什么号称可靠传输的TCP协议,在代码中调用send并成功发出数据,并不意味着这个数据就一定通过物理网络发出去了。

hellojackjiang2011的博客 125

即时通讯安全篇(三):一文读懂常用加解密算法与网络通讯安全

作为开发者,也会经常遇到用户对数据安全的需求,当我们碰到了这些需求后如何解决,如何何种方式保证数据安全,哪种方式最有效,这些问题经常困惑着我们。52im社区本次着重整理了常见的通讯安全问题和加解密算法知识与即时通讯/IM开发同行们一起分享和学习。

hellojackjiang2011的博客 121
上一篇: ChatGPT如何实现聊天一样的实时交互?快速读懂SSE实时“推”技术
下一篇: 移动端弱网优化专题(十五):字节跳动移动端网络HttpDNS优化实践
jackjiang2025
jackjiang2025 网际时代技术分享账号 网际时代技术分享账号
博客等级 码龄8年 700粉丝 318原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值