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

后续扩展

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

相关推荐
Estar.Lee2 小时前
查手机号归属地免费API接口教程
android·网络·后端·网络协议·tcp/ip·oneapi
2401_857610034 小时前
SpringBoot社团管理:安全与维护
spring boot·后端·安全
凌冰_4 小时前
IDEA2023 SpringBoot整合MyBatis(三)
spring boot·后端·mybatis
码农飞飞4 小时前
深入理解Rust的模式匹配
开发语言·后端·rust·模式匹配·解构·结构体和枚举
一个小坑货4 小时前
Rust 的简介
开发语言·后端·rust
monkey_meng5 小时前
【遵守孤儿规则的External trait pattern】
开发语言·后端·rust
Estar.Lee5 小时前
时间操作[计算时间差]免费API接口教程
android·网络·后端·网络协议·tcp/ip
javaDocker6 小时前
业务架构、数据架构、应用架构和技术架构
架构
新知图书6 小时前
Rust编程与项目实战-模块std::thread(之一)
开发语言·后端·rust
盛夏绽放6 小时前
Node.js 和 Socket.IO 实现实时通信
前端·后端·websocket·node.js