关于项目中引入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的维护

后续扩展

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

相关推荐
韩楚风4 分钟前
【linux 多进程并发】linux进程状态与生命周期各阶段转换,进程状态查看分析,助力高性能优化
linux·服务器·性能优化·架构·gnu
杨哥带你写代码23 分钟前
足球青训俱乐部管理:Spring Boot技术驱动
java·spring boot·后端
A尘埃1 小时前
SpringBoot的数据访问
java·spring boot·后端
yang-23071 小时前
端口冲突的解决方案以及SpringBoot自动检测可用端口demo
java·spring boot·后端
Marst Code1 小时前
(Django)初步使用
后端·python·django
代码之光_19801 小时前
SpringBoot校园资料分享平台:设计与实现
java·spring boot·后端
编程老船长1 小时前
第26章 Java操作Mongodb实现数据持久化
数据库·后端·mongodb
IT果果日记2 小时前
DataX+Crontab实现多任务顺序定时同步
后端
姜学迁3 小时前
Rust-枚举
开发语言·后端·rust
爱学习的小健3 小时前
MQTT--Java整合EMQX
后端