太顶了,使用 Netty 实现了一个 IM 即时通讯系统

简介: 太顶了,使用 Netty 实现了一个 IM 即时通讯系统


摘要:通过两篇原理篇的学习,我相信大家对于如何实现一个聊天系统已经有了一个大概的思路了。接下来我们就通过实战,来巩固一下这些知识点,并实现一个在线聊天系统吧。


一、前提回顾

基于 Netty 实现在线聊天系统(原理篇一)

基于 Netty 实现在线聊天系统(原理篇二)

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

二、目录介绍

  • 功能梳理
  • 具体实现

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

三、需求梳理

通过前面两章内容的学习,我们基本学会了如何使用 Netty 建立一个长连接,接下来我们就在这个基础上,实现一个单机版的 im 系统。

主要功能,我梳理了一下:

  • 登录
  • 维持连接、心跳检测
  • 聊天消息
  • 消息ack

使用到的相关组件:

  • SpringBoot-job
  • GuavaCache

四、具体实现

本期的内容是基于,原理篇一的 dome 代码基础上进行的,没有看过的原理一的小伙伴,建议先回顾一下原理篇一。

原理篇一的代码结构:

  • Server(主程序)
  • ServerHandler(业务处理程序)

实战篇一的代码结构:

代码的层级结构如上所示,接下来,我们将会一个个模块对逻辑进行讲解。

1、登录

1)实现逻辑

不管是长连接还是短连接,鉴权这个动作都是要有的,我相信这个功能模块,大家是很好理解的。我这里就不在过多的赘述了,具体实现步骤如下所示:

1、前后端建立 ws 连接

2、前端发送登录类型的报文,如下所示:

{
    "token": "2",
    "type": "10"
}

token:这里的 token,就是用户登录标识,大家可以根据自己所依赖的业务系统,进行修改。

type:这里表示消息报文的类型,本文所有类型定义如下所示:

  • USER_LOGIN (10, "用户上线")
  • USER_LOGIN_RESP (11, "用户上线响应")
  • HEARTBEAT_TIMEOUT (30, "心跳超时")
  • PING (40, "心跳")
  • PONG (41, "心跳响应")
  • CHAT (80, "聊天"),
  • CHAT_RESP (81, "聊天响应")
  • ACK (90, "确认")
  • ACK_RESP (91, "确认响应")
  • UNKNOWN (0, "未知类型")

示例代码如下图所示,WsMsgDispatcher.dispatch

消息类型

3、后端对 token 进行校验,校验成功就记录用户登录信息。

示例代码如下图所示,UserLoginProcessor.login

登录业务逻辑

2)具体效果

主要的业务代码我们已经讲解完毕了,接下来我们来看看效果:

用户登录

从上图,我们可以看到,我们登录的两个用户都成功了,并且返回了对应的用户信息。

2、维持连接、心跳检测

这个模块的功能,其实我们在原理篇二的时候已经讲过了具体的实现方案 了,这里也不再过多的赘述了,我们直接来看具体实现方法吧。

1)维持连接

1、前端每10秒发送一次心跳消息,报文如下所示:

{
    "type": "40",
    "fromId": "2"
}

注:前端发送的每个消息,理论上都是需要带上用户表示的,后端都是需要进行鉴权操作的。我们这里为了方便讲解(偷懒,bushi)将这部分逻辑进行了简化,大家在具体实现的时候,记得一定要加上 鉴权逻辑

2、后端检测,用户是否还在线,如果在线,则刷新用户的最新在线时间,并回复 PONG 消息。

示例代码如下图所示,HeartBeatProcessor.process

维持连接1维持连接2

2)心跳检测

这里主要是基于 IdleStateEvent 事件实现的。

TextWebSocketFrameHandler 继承 SimpleChannelInboundHandler 类,并实现 userEventTriggered 方法,具体代码如下所示:

心跳检测

这里详细说一下,三种事件的区别:

  • readerIdleTimeSeconds: 读超时。即当在指定的时间间隔内没有从 Channel 读取到数据时,会触发一个 READER_IDLEIdleStateEvent 事件。
  • writerIdleTimeSeconds: 写超时。即当在指定的时间间隔内没有数据写入到 Channel 时,会触发一个 WRITER_IDLEIdleStateEvent 事件。
  • allIdleTimeSeconds: 读/写超时。即当在指定的时间间隔内没有读且没有写操作时,会触发一个 ALL_IDLEIdleStateEvent 事件。

所以,我们这里检测 ALL_IDLE 事件即可。

3)具体效果

维持连接效果如下所示:

维持连接效果

心跳检测效果如下所示:

心跳超时效果1

心跳超时效果2

3、聊天消息

聊天消息模块主要分为两部分:

  • 消息接收:客户端推送消息到服务端
  • 消息推送:服务端将消息推送到指定的客户端

这边主要的难点在于,服务端将消息推送到指定的客户端,具体场景有2种情况:

  • 消息的发送者和消息的接受者,在同一台服务器上建立的 ws 连接,这种情况,就很好处理,直接在服务器上找到建立的 ws 连接,然后将消息推送给对应的客户端。
  • 消息的发送者和消息的接受者,在不同的服务器上建立的 ws 连接,这种情况就比较复杂,实现方案也很多,比较简单的实现方式就是,发送一条广播消息,让对应的服务器,将消息推送到指定的客户端。

本文由于是 单机版 的 im,所以只会有第一种情况发生,第二种情况就留给大家自由发挥了。

1)消息接收

具体步骤如下所示:

1、客户端发送类型为80的报文,如下所示:

{
        "type": "80",
        "fromId": "1",
        "toId": "2",
        "content": {
        "contentType": 1,
        "body": "测试消息"
        }
        }

2、服务端(ChatProcessor)对消息进行处理,具体代码如下所示:

消息接收

2)消息推送

具体步骤如下所示:

1、获取消息接受者所连接的服务器 ip 地址 2、判断当前服务器 ip 地址是否和上面的 ip 地址相同,如果相同则推送消息,否则转发给目标服务器

具体代码如下所示:

消息推送

3)具体效果

1、我们先登录两个用户,分别是张三、李四,如下图所示:

聊天登录

2、张三发送消息给李四,如下图所示:

张三发送消息给李四

3、李四发送消息给张三,如下图所示:

李四发送消息给张三

4、消息 ack

因为网络环境异常或者其他异常状况的发送,可能会出现消息推送失败的情况,这时候就需要 消息 ack 机制和重试,来保证我们的消息可以推送成功。

1)消息 ack 机制

具体步骤如下:

1、客户端收到 80 类型的消息,解析并发送 ack 报文,如下所示:

{
        "type": "90",
        "msgId": "2bfea133-72a8-4315-82aa-80049fe4fb7b"
        }

2、服务端收到 ack 消息,变更消息状态(AckProcessor),具体代码如下图所示:

消息ack

2)消息重试

这里因为是单机版 im,所以直接采用 SpringBoot-Job 实现,Job 代码如下所示:

消息重试

总结

好了我们实战篇一,到这里结束了,希望大家都能跟着文中的思路,具体去实现一遍,如果遇到什么问题或者文中有什么错误的地方,欢迎大家留言。谢谢观看,点个赞再走吧。



相关文章
|
17天前
|
网络协议 NoSQL API
转转客服IM系统的WebSocket集群架构设计和部署方案
客服IM系统是转转自研的在线客服系统,是用户和转转客服沟通的重要工具,主要包括机器人客服、人工客服、会话分配、技能组管理等功能。在这套系统中,我们使用了很多开源框架和中间件,今天讲一下客服IM系统中WebSocket集群的的实践和应用。
78 0
|
2月前
|
前端开发 JavaScript Java
智能客服系统的技术栈解析-唯一客服系统技术架构优势
“唯一客服系统”采用 Vue.js 2.x + ElementUI 构建前端,实现响应式界面,支持多端适配;后端基于 Golang + Gin + GORM,具备高性能与高并发处理能力。系统支持私有化部署,提供灵活定制、AI 扩展能力,技术栈简洁易维护,兼顾开发者友好与企业级应用需求。
169 1
|
2月前
|
消息中间件 负载均衡 中间件
⚡ 构建真正的高性能即时通讯服务:基于 Netty 集群的架构设计与实现
本文介绍了如何基于 Netty 构建分布式即时通讯集群。随着用户量增长,单体架构面临性能瓶颈,文章对比了三种集群方案:Nginx 负载均衡、注册中心服务发现与基于 ZooKeeper 的消息路由架构。最终选择第三种方案,通过 ZooKeeper 实现服务注册发现与消息路由,并结合 RabbitMQ 支持跨服务器消息广播。文中还详细讲解了 ZooKeeper 搭建、Netty 集群改造、动态端口分配、服务注册、负载均衡及消息广播的实现,构建了一个高可用、可水平扩展的即时通讯系统。
237 0
|
移动开发 网络协议 小程序
基于开源IM即时通讯框架MobileIMSDK:RainbowChat-iOS端v10.0版已发布
RainbowChat是一套基于开源IM即时通讯聊天框架 MobileIMSDK 的产品级移动端IM系统。RainbowChat源于真实运营的产品,解决了大量的屏幕适配、细节优化、机器兼容问题。RainbowChat可能是市面上提供im即时通讯聊天源码的,唯一一款同时支持TCP、UDP两种通信协议的IM产品。与姊妹产品RainbowTalk和RainbowChat-Web 技术同源,历经考验。
14 0
基于开源IM即时通讯框架MobileIMSDK:RainbowChat-iOS端v10.0版已发布
|
2月前
|
测试技术 Go
客服系统程序入口文件解析-唯一客服系统源码开发
该代码为 Go 语言编写的客服系统命令行程序入口,结构清晰,使用 cmd 包启动业务逻辑,可能基于 cobra 框架实现,具备良好可扩展性与可维护性,适用于服务启动与管理。
163 69
|
1月前
|
数据安全/隐私保护 容器 Go
开源IM即时通讯系统调研
Lumen IM 是一款企业级开源即时通讯工具,前端采用 Vue3 + Naive UI,后端基于 Go 语言,使用 WebSocket 协议。支持 Docker + Nginx 快速部署,适合私有化环境。功能包括文本、图片、文件消息,内置笔记、群聊及消息历史记录。界面美观、功能完善,适用于企业沟通、团队协作及开发者学习。提供前后端源码,便于快速搭建 IM 系统。
开源IM即时通讯系统调研
|
1月前
|
移动开发 网络协议 小程序
鸿蒙NEXT即时通讯/IM系统RinbowTalk v2.4版发布,基于MobileIMSDK框架、ArkTS编写
RainbowTalk是一套基于开源即时通讯讯IM框架 MobileIMSDK 的产品级鸿蒙NEXT端IM系统。纯ArkTS编写、全新开发,没有套壳、也没走捷径,每一行代码都够“纯血”。与姊妹产品RainbowChat和RainbowChat-Web 技术同源,历经考验。
77 1
|
2月前
|
机器学习/深度学习 人工智能 自然语言处理
从0搭建AI智能客服教程(AI智能客服系统选型和实战指南)
针对智能客服技术与业务脱节的痛点,合力亿捷通过 NLP、知识图谱及人机协同策略,助企业实现首次解决率超 70%、人力成本降 43%、年省成本超千万。其方案提升制造业问题解决率 40%,投诉转接成功率达 99%,以分场景选型助力超万家企业平衡业务与成本,成行业首选。
|
2月前
|
缓存 移动开发 网络协议
纯血鸿蒙NEXT即时通讯/IM系统:RinbowTalk正式发布,全源码、纯ArkTS编写
RainbowTalk是一套基于MobileIMSDK的产品级鸿蒙NEXT端IM系统,目前已正式发布。纯ArkTS、从零编写,无套壳、没走捷径,每一行代码都够“纯”(详见:《RainbowTalk详细介绍》)。 MobileIMSDK是一整套开源IM即时通讯框架,历经10年,超轻量级、高度提炼,一套API优雅支持 UDP 、TCP 、WebSocket 三种协议,支持 iOS、Android、H5、标准Java、小程序、Uniapp、鸿蒙NEXT,服务端基于Netty编写。
191 1
|
2月前
|
移动开发 缓存 前端开发
可二次开发的在线客服系统-前后端混合渲染模式
服务端渲染(SSR)结合API交互,提升首屏加载速度与SEO友好性,适用于混合渲染模式的Web应用。
57 0