SpringCloud Gateway Netty Websocket实现高性能聊天系统集群方案

目录

一、问题引出

二、架构图

三、实现方式


一、问题引出

在IM分布式系统的构建中遇到的问题:

Netty服务器通过客户端的连接信息来生成对应的Channel(可以理解为长连接的用户信息),Netty服务器通过Channel来进行消息转发。于是,提出初始构想:通过Redis来序列化Channel,再通过Netty服务器去获取Redis上的Channel,最后转发。但这个构思是错误的,因为Channel是硬件的连接信息,并不能被序列化。

最终构思解决Channel共享的方案有两个:

(1)GateWay网关来自定义负载均衡,当接收到Websocket消息时直接根据用户id进行路由,该方式完美兼容原始功能,原始功能采用Netty来开发Websocket,实现难度低,开发成本低。

(2)采用Netty高性能框架开发Websocket,通过MQ消息队列进行广播来实现Channel的共享,实现难度不大,开发成本较高。

二、架构图

最终,我选择第二种解决方案,IM系统架构如下:

 

三、实现方式

首先,我先搭建一个支持简单聊天的Netty-Websocket聊天服务器,之后,我先构建一个消息聊天对象如下:

package com.dragonwu.im.domain.dto;import com.dragonwu.common.basic.constant.Constants;
import com.dragonwu.common.security.basic.domain.emums.LoginType;
import com.dragonwu.im.domain.enums.FromUserType;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;/*** @author Dragon Wu* @since 2023/2/27 13:05* 消息对象*/
@Getter
@Setter
@ToString
@Document("im_message") //集合名
// {"msg":"你的消息","loginType":"你的类型","userId":"你的id","to":"接收者","group":"群接受对象","isCustomerService":"是否为客服","isVisitor":"是否为游客",
// "isConnect":"是否为连接信息"}
public class IMessage implements Serializable {@Id //存入mongo里的idprivate String id;//登录类型private String loginType;//用户id@Indexedprivate String userId;//发送时间private LocalDateTime sendTime;//发送人idprivate String to;//群发列表private List<String> group;//发送者是否为客服private Boolean isCustomerService;//发送者是否为游客private Boolean isVisitor;//发送的消息private String msg;//是否为第一次连接信号private Boolean isConnect;@CreatedDate //创建时默认创建该时间字段private LocalDateTime createTime;/* 判断消息格式是否正确 */public boolean isMsgOK() {if (Objects.isNull(isVisitor)) {isVisitor = false;}if (Objects.isNull(to)) {to = Constants.EMPTY_STR;}if (Objects.isNull(isConnect)) {isConnect = false;}try {if ((!StringUtils.isEmpty(userId)) && (!StringUtils.isEmpty(msg))) {return ((!StringUtils.isEmpty(to)) || ((group != null) && (!group.isEmpty())) || isVisitor);}} catch (NullPointerException ignored) {}return false;}//获取发送者的类型public FromUserType getFromUserType() {LoginType exists = LoginType.isExists(loginType);if (Objects.isNull(isVisitor)) {isVisitor = false;}if (Objects.isNull(isCustomerService)) {isCustomerService = false;}if (Objects.isNull(exists) && isVisitor) {return FromUserType.VISITOR_TYPE;} else if ((exists == LoginType.USER_TYPE) && isCustomerService) {return FromUserType.CUSTOMER_SERVICE;} else if (exists == LoginType.USER_TYPE) {return FromUserType.USER_TYPE;} else if (exists == LoginType.CUSTOMER_TYPE) {return FromUserType.CUSTOMER_TYPE;}return null;}public void setNowAsSendTime() {sendTime = LocalDateTime.now();}public boolean isGroupChat() {if (group != null) {return StringUtils.isEmpty(to) && (!group.isEmpty()) && (!isVisitor);}return false;}
}

有了这样的对象以后,我便可对发送过来的消息进行序列化与反序列化获取数据,通过消息对象中的数据是否正确与是否认证来决定消息的转发。

每个用户第一次发送isConnect型号时将其注册到Redis中,Key为用户名唯一,Value为ChannelId的asShort值。当用户在不同Netty服务器上时(此时发送与接收者都在线),我会先让服务器去Redis获取对应用户名的ChannelId,先在本地服务器中查找,若查询到该ChannelId的Channel则直接转发,否则为不在同一个Netty服务器上,发送Channel寻找的信号到MQ进行广播,其他服务器获取到广播后查询直接是否有该ChannelId的Channel,若有则转发;离线消息的话,直接以Zset的形式加入Redis即可,当用户上线时再拉取数据。最后,无论哪种情况发送的消息,都会被MQ进行集群负载均衡来存储到数据库中。

以上,为个人本次实践的总结,希望对遇到相似问题的开发者,有所帮助,有问题可联系共同探讨!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/38413.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

oracle 锁表是为什么,怎么解决

1、锁表发生在insert update 、delete 中 2、锁表的原理是 数据库使用独占式封锁机制&#xff0c;当执行上面的语句时&#xff0c;对表进行锁住&#xff0c;直到发生commite 或者 回滚 或者退出数据库用户 3、锁表的原因 第一、 A程序执行了对 tableA 的 insert &#xff…

oracle 查询事务锁,Oracle中事务锁(锁住的表、锁住的会话)

今天又学会一招&#xff0c;查看Oracle数据库中由于会话非正常退出而导致的事务锁&#xff1a; 1.查看锁住的表 SELECT b.owner,b.object_name,a.sessi 今天又学会一招&#xff0c;查看Oracle数据库中由于会话非正常退出而导致的事务锁&#xff1a; 1.查看锁住的表 SELECT b.ow…

PG 锁类型、级别、死锁解决

文章目录 锁类型ACCESS SHAREROW SHAREROW EXCLUSIVESHARE UPDATE EXCLUSIVESHARESHARE ROW EXCLUSIVEEXCLUSIVEACCESS EXCLUSIVE 死锁查询死锁处理死锁测试Session ASession BSession CSession DSession E原因 结论 锁类型 ACCESS SHARE 1、SELECT产生的锁 2、与ACCESS EXCLU…

Oracle死锁问题: enq: TX - row lock contention

前言 这篇文章也是记录近期遇到的问题以及从中学到的知识 &#xff0c;近期一直在救火&#xff0c;有些问题自认为还是挺有代表性的&#xff0c;有兴趣的话再继续向下看 问题现象 线上反馈&#xff0c;执行批量处理EXCEL数据时&#xff0c;系统一直卡在进度滚动条界面。处理任务…

Oracle 出现锁表了,如何处理

出现锁表的情况很多种&#xff0c;但是大部分情况都是更新表&#xff0c;然后并没有提交&#xff0c;导致数据库的表被锁的情况。处理方式也比较简单&#xff0c;如下&#xff1a; 查询是否有表锁&#xff1a; select count(1) count from v$locked_object; 如果查询出来的数量…

短文重复性检测综述,谷歌文本重复性检测: Detect duplicate content like Google

文本重复性检测一直是NLP等领域非常重要的一项研究工作&#xff0c;今天 #paperClub# 给大家翻译一下"Detect duplicate content like Google"。 重复的内容是影响网站排名的最重要的负面因素之一。这就是为什么近重复检测 (NDD) 在任何 SEO 应执行的任务之间占据重要…

词云图:统计一个文本中词出现的次数。

在进行词云图的创作时&#xff0c;统计词语的出现频率是非常有意义的&#xff0c;可以依据词语频率的高低来判断词云图是否准确。选择小说中的某一章节&#xff0c;利用程序统计词语出现的次数。 程序如下&#xff1a; # -*- codeing utf-8 -*- # Time : 2021/12/12 1:21 # A…

chatgpt赋能python:Python词语分类

Python词语分类 Python是一种高级编程语言&#xff0c;它有很多词语&#xff0c;其中一些可能令你在学习Python时感到困惑。在这篇文章中&#xff0c;我们将探讨Python词语的分类&#xff0c;以帮助您更好地理解Python编程。 变量与数据类型 在Python中&#xff0c;变量用于…

DaVinci:Camera Raw(ARRI)

本文主要介绍 ARRI 的 Raw 格式素材相关的 Camera Raw 参数。 解码质量 Decode Quality 解码质量决定了图像解拜耳之后所呈现的素质&#xff0c;也与最终的输出息息相关。 默认为“使用项目设置” Use project setting&#xff0c;表示使用项目设置对话框中的“Camera RAW”解码…

DaVinci_Resolve_Studio_18.1.1达芬奇图文安装教程及下载

DaVinci Resolve最大的特点是&#xff0c;将剪辑、调色、视觉特效、动态图形和音频后期制作融于一身&#xff0c;它采用美观新颖的界面设计&#xff0c;易学易用&#xff0c;能让新手用户快速上手操作&#xff0c;还能提供专业人士需要的强大性能。 DaVinci Resolve 18是一次重…

davinci使用笔记(1)

第一节主要介绍达芬奇17的各个界面以及第一次使用的注意事项和主要设置。 这是达芬奇打开出现的界面&#xff0c;如图这是一个项目工程界面&#xff0c;我们可以在这里新建新的项目和和对项目进行分类&#xff0c;在这个界面右下角有三个按钮&#xff0c;其中第二个按钮是新建文…

达芬奇调色DaVinci Resolve Studio18v18.1.4 2023中文版更新发布,支持intel/M1/M2芯片

达芬奇是世界上唯一在单一软件环境中进行剪辑、调色、视觉效果、图形和音频后期处理的解决方案。其现代、时尚的界面简单直观&#xff0c;对于新手和有经验的用户来说都足够了。 DaVinci Resolve 无需掌握多个应用程序或在不同系统之间切换&#xff0c;极大地简化了您的创作过…

TI DaVinci(达芬奇)入门

&#xff08;转载来自 德州仪器半导体技术&#xff08;上海&#xff09;有限公司 通用DSP 技术应用工程师 崔晶 德州仪器&#xff08;TI&#xff09;的第一颗达芬奇&#xff08;DaVinci&#xff09;芯片&#xff08;处理器&#xff09;DM6446已经问世快三年了。继DM644x之后&am…

davinci 达芬奇BI工具

Davinci 是一个 DVAAS&#xff08;Data Visualization as a Service&#xff09;平台解决方案&#xff0c;面向业务人员/数据工程师/数据分析师/数据科学家&#xff0c;致力于提供一站式数据可视化解决方案。既可作为公有云/私有云独立部署使用&#xff0c;也可作为可视化插件集…

ChatGPT3.0 text-davinci-003 表现诡异

最近想试用一下通过API调用ChatGPT&#xff0c;在测试 gpt-3.5-turbo 的时候遇到了“openai.error.InvalidRequestError: This is not a chat model and thus not supported in the v1/chat/completions endpoint. Did you mean to use v1/completions? ”的问题。 所以该尝试…

中国元宇宙科技有限公司+《星云虚境》+AI虚拟数字人+chatgpt

随着人工智能、虚拟现实等技术的不断发展&#xff0c;中国元宇宙科技有限公司计划推出一款名为《星云虚境》的虚拟数字人平台。该平台将采用AIchatgpt等技术&#xff0c;为用户提供更加真实、智能的虚拟人体交互体验&#xff0c;为未来的数字化生活带来新的可能性。 未来&…

辅助现实?aR?AR?进入元宇宙,这个概念得搞懂

1 什么是辅助现实&#xff1f; 辅助现实&#xff08;aR&#xff0c;assisted Reality&#xff09;这个词在最近的一些AR眼镜的新品发布会频繁出现。那这辅助现实又是什么&#xff0c;与增强现实之间有什么关系呢&#xff1f; 其实&#xff0c;辅助现实可以说是增强现实里面的一…

元宇宙系列之AI虚拟人:“人”潮汹涌 探路未来

尽管元宇宙尚处不断扩充定义的进程中&#xff0c;但市场对于虚拟人在其中扮演关键要素已达成一定共识。我们认为&#xff0c;从中短期视角看&#xff0c;虚拟人相关技术逐步落地&#xff0c;应用场景持续拓宽&#xff0c;或为元宇宙概念下技术、内容及产业融合升级的初步尝试&a…

ChatGPT和AI会重燃中国的虚拟宇宙吗?

随着像 Meta 这样的科技巨头关闭他们的元宇宙部门以支持人工智能 &#xff08;AI&#xff09; 的努力——尽管他们认为元宇宙仍将是其主要产品——观众们相信&#xff0c;以前备受赞誉的虚拟生态系统已经被 AI 淘金热从互联网宝座上推倒了。 人工智能的利润潜力在今年上半年吸…

元宇宙虚拟人迎来高峰期,哪个是你的最爱?

虚拟人从最初的不温不火&#xff0c;到现在步入“出生高峰期”&#xff0c;元宇宙可以说是功不可没。 此前&#xff0c;量子位发布了《虚拟数字人深度产业报告》&#xff0c;报告显示&#xff0c;到2030年我国虚拟数字人整体市场规模将达到2700亿元。其中&#xff0c;“身份型…