关于项目中引入IM服务的技术挑战与解决方案

大家好,我是小趴菜,本次我分享一下关于我们项目中引入IM服务的一些技术挑战与解决方案

对于网络通信,我们可以使用NIO,Mina,Netty来实现,但是NIO开发复杂,API较多,这就导致我们的研发成本就会提高,所以我们使用了当前最流行的Netty来实现我们的IM服务

我们项目中主要是涉及网页版的单人聊天,接下来我们分析一下项目中遇到的挑战以及解决思路

对于一个IM服务来说,我们要把保证数据的安全性,可靠性,唯一性

消息可靠性

对于一条IM消息来说,可靠性是要保证发送方能将一条消息准确的完整的发送给接收方,一条消息的发送流程也就包括以下几个步骤

1:发送方发送一条消息给IM服务器

2:IM服务器将这条消息保存到MySql中,保存成功之后,发送一个ACK给发送方,来告诉发送方,你的消息已经成功发送到了IM服务器

3:IM服务器将消息推送给接收方

4:接收方收到消息之后,发送一个ACk给IM服务器,告诉IM服务器这条消息已经接收到了

那么消息在哪些步骤中可能会发生丢失呢??

  • 1:消息发送给IM服务器,这时候由于网络或者其它原因,都有可能导致IM服务器接收不到这条消息

  • 2:IM服务器接收到这条消息了,也将消息成功保存到了MySql,但是这时候发送ACk的时候,发送失败了,这就可能导致发送方接收不到这条消息的ACK

  • 3:IM服务器将消息推送给接收方,但是由于网络或者其它原因,导致接收方根本就没有收到这条消息

  • 4:接收方收到这条消息了,但是在发送ACk的时候失败了,导致IM服务器没有接收到这条消息的ACk确认消息

所以以上几个步骤都有可能出现消息丢失的情况,所以接下来我们来一个一个的解决

解决方案

发送方要确定这条消息是否已经成功发送到IM服务器,就是通过IM服务器发送的确认ACk消息来确认的,这时候如果在一定的时间内,发送方没有接收到ACK确认消息,这时候我们可以通过重试机制来重新发送这条消息,当然也不能一直重试,我们要限制重试次数,直到发送方接收到了这条消息的ACK,这样就可以确定这条消息已经成功保存到了IM服务器了

当然在接收方一端处理方式也一样,在一定的时间内,我们IM服务器没有接收到这条消息的ACK消息,那么服务端就再次推送这条消息给接收方,直到收到这条消息的ACK确认消息

消息的唯一性

虽然我们可以通过重试机制来保证消息能成功发送到IM服务器,也可以通过重试机制来将消息推送给接收方,我们还是来看下整个流程

  • 1:第三步的时候,我们发送ACK消息失败了,这时候发送方没接收到ACK那么就会重试,这时候服务端就会出现消息重复的情况,也就是一条消息会被存几份
  • 2:第六步的时候,IM服务器没有接收到接收方发送的ACK,这时候IM服务器就会重新将这条消息发送给接收方,那么接收方就会出现重复的数据

解决方案

所以我们要做好消息的唯一性,做好去重的处理,比如说我们给每一条消息设置一个唯一值,比如UUID,雪花算法,redis的自增

消息有序性

对于一个IM系统,消息是一定要保证有序性,如果消息无序,那么同样一句话表达的意思就有可能是完全不一样,所以我们必须要保证消息的有序性

对于消息的有序性,我们可以根据消息的唯一ID来实现,所以这时候UUID就不适合了,但是雪花算法也有可能是会重复的,所以项目中我们是使用redis的自增来实现

但是这时候有个问题,redis的自增是有一个上限的,但是项目中本身就是网页版的,不像是微信这种交友聊天,所以使用redis的自增,完全可以满足我们的业务需求,如果大家想知道微信这种有序实现方案,可以参考 code84.com/126194.html

所以最终在项目中我们决定使用redis的自增方式来实现消息的唯一值,后续就可以根据这个唯一的值来实现消息的有序性,当然就增加了redis的维护成本,以及如果后续redis崩了,那么就无法为消息生成唯一值了,所以相对应的也增加了redis的维护

后续扩展

后续就有可能还会实现消息的已读,未读功能,当然大家还可以进行扩展,比如客户端重练如何加载之前的聊天记录,当然在当前项目中是不需要实现的,客户端重连你不需要加载之前的聊天记录信息。

相关推荐
coderSong25682 小时前
Java高级 |【实验八】springboot 使用Websocket
java·spring boot·后端·websocket
Mr_Air_Boy3 小时前
SpringBoot使用dynamic配置多数据源时使用@Transactional事务在非primary的数据源上遇到的问题
java·spring boot·后端
打码人的日常分享4 小时前
物联网智慧医院建设方案(PPT)
大数据·物联网·架构·流程图·智慧城市·制造
咖啡啡不加糖4 小时前
Redis大key产生、排查与优化实践
java·数据库·redis·后端·缓存
白水baishui4 小时前
搭建强化推荐的决策服务架构
架构·推荐系统·强化学习·决策服务·服务架构
何双新5 小时前
第23讲、Odoo18 邮件系统整体架构
ai·架构
雪碧聊技术5 小时前
将单体架构项目拆分成微服务时的两种工程结构
微服务·架构·module·project·工程结构
大鸡腿同学5 小时前
纳瓦尔宝典
后端
江城开朗的豌豆5 小时前
JavaScript篇:函数间的悄悄话:callee和caller的那些事儿
javascript·面试