首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >转转客服IM聊天系统背后的技术挑战和实践分享

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

作者头像
JackJiang
发布2025-11-11 19:59:32
发布2025-11-11 19:59:32
1760
举报
文章被收录于专栏:即时通讯技术即时通讯技术

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

1、引言

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

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

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

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

2、关于作者

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

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

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

这里关键的点是:

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

方案1:长短轮询

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

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

方案2:WebSocket

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

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

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

如图是一条消息发送的核心步骤,整个过程中可以分为两个部分,消息由客户端发送到服务端(第1、2步),服务端将消息推送至另一个客户端(第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实现机制:

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

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

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

具体是:

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

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

7、心跳保活机制

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

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

心跳机制设计如下。

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

服务端:

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

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

8、消息协议的设计

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

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

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

9、本文小结

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

在未来的发展中,我们将继续优化和完善,以应对不断变化的需求和用户期望,为用户提供更加优质的服务体验。(本文已同步发布于:http://www.52im.net/thread-4874-1-1.html

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开发的那些坑:架构设计、通信协议和客户端

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、引言
  • 2、关于作者
  • 3、如何保证聊天消息的实时性
  • 4、什么是聊天消息的可靠性
  • 5、如何保证聊天消息触必达?
  • 6、如何对聊天消息去重?
  • 7、心跳保活机制
  • 8、消息协议的设计
  • 9、本文小结
  • 10、参考资料
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档