设为首页 - 加入收藏
广告 1000x90
您的当前位置:主页 > 资源 > 效果代码 > 正文

得物从0到1自研客服IM系统的技术实践之路

来源:未知 编辑:天选资讯 时间:2023-03-27

  本文由得物技术王卫强分享,为了更好的阅读体验,有较多的内容修订和排版优化。

  客服IM的核心业务其实就是在线沟通,客服IM的好处是使得客服与用户通过实时沟通的方式可以在最短的时间内帮助用户解决问题。

  为了快速支撑公司业务发展需求,我们客服IM在发展初期是基于第三方的云IM SDK进行二次开发而来。虽然提升了项目进展,但同时也埋下了问题定位困难、特殊功能实现成本高等隐患。

  随着公司业务的高速发展,客服对IM聊天的性能和体验都有了更高的要求,在第三方云IM SDK消息通信上逐渐遇到了技术瓶颈。为解决租用第三方云IM SDK接入带来的潜在隐患、提升IM的稳定性和高扩展性,自研一套可控、稳定、灵活的IM系统已是迫在眉睫了。

  本篇文章将基于工程实践,分享我们从0到1自研一套客服IM系统时在各种关键技术点上的设计思路和实践方法。

  - 移动端IM开发入门文章:《新手入门一篇就够:从零开发移动端IM》- 开源IM框架源码:(备用地址点此)

  客服与用户在聊天的过程中,直观上就是客服在输入文案,然后通过网络发送给用户。

  但是IM聊天SDK该如何设计才能使客服在发送消息过程中感知不到卡顿?这一点是非常关键的,要避免卡顿就要设计合理的发送策略以及避免大量JS脚本执行。

  客服发送了“客服小冰为您服务”这个文案,通过业务侧调用SDK的接口,传入到SDK;

  再将该数据存储到数据池中,序列化后把这个数据对象data传递给socket接口,通过网络通道发送到网关;

  网关侧接收到消息后,再反序列化,传递到数据池中进行处理,组装成业务可识别的model,推送到业务侧使用。

  针对第1)点,SDK会先创建消息体,即把这个字符串封装成一个自定义的结构体model。

  从上图中可以清晰地看出一条消息发送和接收的完整流程链路。如果IM的SDK设计不合理,发送消息和接收消息流程出现了卡顿,将直接影响用户的体验。

  在IM SDK自研开发过程中,如何解耦框架代码和业务代码,做到灵活的消息监听,前期调研之后使用了RxJS。

  SDK底层在接收到数据后需要同步到业务侧,之前的做法是通过监听方式实现,这种方式不具备取消订阅的能力,维护成本相对较高。而使用RxJS可以清晰的梳理出数据流向,通过发布订阅的方式实现数据的通信。

  从上图可以看到消息处理的整个流向非常清晰,框架底层接收消息,订阅者消费消息。

  网络协议我们选择的是TCP协议。我们为什么没有选择UDP呢?因为UDP是无连接的、不够安全、无法提供可靠传输的服务,通过TCP连接传送的数据可以无差别、不丢失、不重复且按序到达。

  PS:尺有所短、寸有所长,TCP和UDP的优劣应该客观看待,感兴趣可以深入学习下面的文章:

  首先我们要做的就是建立Websocket连接:代码层面我们会先创建一个Connection的抽象类,主要处理网络连接相关配置、超时后重新连接的补偿实现,和一些继承类需要实现的抽象方法。

  如上述代码所示:核心在处理超时重连,传统的重试策略是每隔一段时间重试一次,由于是固定的时间间隔重试,重试时又会有大量的请求在同一时刻涌入,会不断地造成限流。(这里使用了指数退避的方式,指数退避是一种通过反馈,成倍地降低某个过程的速率,以逐渐找到合适速率的算法,可根据时隙和重试尝试次数来决定延迟重试。)

  至此:网络层连接就已完成了,相对比较简单,都是一些socket api的封装,核心的点在用指数退避算法实现消息发送失败重连接。

  数据链路层是IM SDK的核心层,主要涉及到用户信息、聊天消息、数据池等等,我们来一步步对每个模块进行分析。

  消息协议类型非常重要,是消息发送的基石。初始化协议数据体,可以用于后续各种消息、事件的发送。

  Hi:发送客户端基础信息,告诉server当前client的版本、设备类型、语言等信息;

  Login: 登录,token验证,获取或创建当前用户topic信息;

  Get: 获取topic的metadata信息,例如:获取订阅者列表、历史数据等;

  Set: 更新topic的metadata信息,例如:删除消息或删除topic;

  Del: 用于删除操作,包括删除消息、删除订阅关系、删除topic等;

  Note: client发送通知给topic的订阅者,例如消息已收到,消息已读,当前正在输入等;

  客服要发送一条消息,肯定有对应的消息结构体model,即需要对消息体进行设计,这里会设计一下message类,每次创建新的消息体都会new一个实例,通过对实例的操作可以更新消息状态等。

  这里还涉及到消息体的一些基本操作方法对数据池中的数据进行操作,就不做过多的阐述。

  上面都是在分析公共模块,但是客服和用户是一对多的关系存在,还需要设计一个用户维度模块,后续在业务侧的操作基本都是以用户维度来操作,需要从单个用户维度设计对应的订阅关系、消息发送、删除等等。

  针对客服发送消息,我们首先要站在客服角度考虑消息是否已发出去,优先展示的聊天页面,而不是等网关给了回复后再展示到聊天页面。

  根据已往经验来看,只要回车消息就要立即展示到聊天页面,否则客服会认为出现了卡顿,体验效果不佳,鉴于这种场景的需求,在设计发送消息链路的时候就要充分考虑到这一点。

  如上图所示:先在SDK内进行处理对应的消息,处理完成后返回到业务侧完成渲染后再进行消息发送到网关,正常情况下都在一帧之内,客服是感知不到有延迟的。这里要关注消息体序列化、反序列化的时机,避免无谓的性能浪费。

  上述图中有个虚拟seq:主要是为了在未收到IM网关响应之前进行排序用的,比如图片、视频、断网发送消息、消息发送失败,或收到IM网关回复缺少seq(场景:敏感词)等情况都需要通过虚拟seq进行准确排序。

  接收消息过程相对比较简单,收到消息进行反序列化后更新相关数据,然后在数据池中完成去重(重试机制)、排序后更新到业务侧渲染即可(如下图所示)。

  IM消息的可靠传递主要是指:消息在发送接收过程中,能够做到不丢消息、消息不重复、消息顺序不错乱。

  第二种情况:消息在IM网关存储完后,客服A被告知消息发送成功了,然后IM网关把消息推送给用户A的在线)

  如果用户A的设备在接收到消息,在后续处理过程中出现问题,也会导致消息丢失。

  针对第2)点,具体场景比如:用户A的设备在把消息写入本地DB时,出现异常导致落库失败,这种情况下,由于网络层面实际上已经成功传输,但用户A却看不到消息。

  我们客服IM对于消息丢失的处理方案主要是参考TCP协议的ACK机制,实现了一套基于业务层的ACK协议。

  在TCP协议中,默认提供了ACK机制,通过一个协议自带的标准的ACK数据包,来对通信方接收的数据进行确认,告知通信发送方已确认成功接收了数据。ACK机制也是类似,需要解决的是:IM网关推送后如何确认消息是否成功送达接收方并明确被接收方所接收。

  客服或用户在发送消息的过程中都会携带一个msgid(32位的uuid,类似TCP的sequenceId),IM网关在接收到消息后,会根据msgid到数据库中查询是否存在该条消息,如果存在就不落库,如果不存在就落库。

  然后再推送到接收方,接收方在收到消息后会回复ACK,ACK包中会携带上当前最新的seqid,IM网关收到ACK回复后会对最大的seqid进行更新。

  这里为什么要更新最大seqid呢?这么设计肯定有一定道理的,IM网关在收到发送方发送的消息后除了到数据库中检测该消息是否存在外,还会对比当前接收到消息的seq和最大seqid两者之间的差值,会把[seq, seqid)之间的数据全部推到接收方,正常情况下都是[n, n-1),如果IM网关没有收到接收方ACK,n-1就不会更新,推送的消息个数就大于1了。如果seq和seqid相等那就是发送方重复推送的消息,这个时候就不会向接收方推送。这里就涉及到了消息重试,继续向下分析吧。

  上述图片中的数据只是模拟消息重试,真实场景中执行频次肯定要比这个时间更久一些。

  IM网关服务是集群部署,会通过topic和seqid作为唯一索引,在接收到消息落库之前会生成seqid,客服端和用户端接收到发送消息的回执时需要根据返回的seqid(IM网关自增)进行消息排序,这种方式可取。

  通过以上的分析:客服IM消息的可靠性就是通过ACK机制、重试机制、去重机制、排序机制来确保每一条消息的完整触达和准确排序。

  就拿我们客服业务来说:有些特定消息是不需要展示到聊天页面的(比如:用户发送消息被篡改等)。当然我们在业务侧重新对数据过滤或者渲染的时候也是可以做过滤的,这样操作是没什么问题,但是没有必要,如果不从源头过滤数据,后续参与二分、倒序查找的源数据也会增加。会有一些不必要的浪费。当然也可以不添加这个参数,SDK都是全兼容的。

  至此我们就完成了整个SDK的实现以及在业务侧的使用,消息发送和接收也都正常。

  自研IM SDK还是蛮有挑战的一件事情,从单纯的基于第三方SDK二次开发到自研SDK并与我们的实际业务场景相对完美的结合。

相关推荐:

网友评论:

发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片

织梦模板大全 dedecms.codesdq 联系QQ:121673232 邮箱:121673232@qq.com

Copyright © 2002-2011 DEDECMS. 织梦科技 版权所有 Power by DedeCms

Top