项目实战之RabbitMQ冗余双写架构

🧑‍💻作者名称:DaenCode
🎤作者简介:啥技术都喜欢捣鼓捣鼓,喜欢分享技术、经验、生活。
😎人生感悟:尝尽人生百味,方知世间冷暖。
📖所属专栏:项目所感所想


在这里插入图片描述


文章目录

  • 🌟架构图
  • 🌟application.properties
  • 🌟RabbitMQ配置
  • 🌟消息协议封装
  • 🌟消息类型封装
  • 🌟C端消费者
  • 🌟B端消费者
  • 🌟发送消息与处理消息
  • 🌟最后

🌟架构图

在这里插入图片描述

🌟application.properties

redundancy.mq.redundancy-event-exchange=redundancy.event.exchange
redundancy.mq.add-routing-key=redundancy.add.business.consumer.routing.key
redundancy.mq.add-business-binding-key=redundancy.add.business.*.routing.key
redundancy.mq.add-consumer-binding-key=redundancy.add.*.consumer.routing.key
redundancy.mq.add-business-queue=redundancy.add.business.queue
redundancy.mq.add-consumer-queue=redundancy.add.consumer.queue

🌟RabbitMQ配置

package top.daencode.config;import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.Exchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** Copyright (C) 2023-11-29  智源恩创网络科技工作室** @BelongsProject: architecture-solution* @BelongsPackage: top.daencode.mq* @author: DaenCode* @createTime: 2023-11-29  15:08* @description: TODO* @version: 1.0*/
@Configuration
@Slf4j
@Data
@ConfigurationProperties(prefix = "redundancy.mq")
public class RabbitMqForRedundancyConfig {/*** 交换机*/private String redundancyEventExchange;/*** 添加路由key*/private String addRoutingkey;/*** B端添加绑定key*/private String addBusinessBindingKey;/*** C端添加绑定key*/private String addConsumerBindingKey;/*** B端添加队列*/private String addBusinessQueue;/*** C端添加队列*/private String addConsumerQueue;/*** 创建冗余双写交换机* @return*/@Beanpublic Exchange redundancyEventExchange(){return new TopicExchange(redundancyEventExchange);}/*** 创建B端添加队列* @return*/@Beanpublic Queue addBusinessQueue(){return new Queue(addBusinessQueue,true,false,false);}/*** 创建C端添加队列* @return*/@Beanpublic Queue addConsumerQueue(){return new Queue(addConsumerQueue,true,false,false);}/*** B端绑定关系*/@Beanpublic Binding addBusinessBinding(){return new Binding(addBusinessQueue, Binding.DestinationType.QUEUE,redundancyEventExchange,addBusinessBindingKey,null);}/*** C端交换机绑定到队列* @return*/@Beanpublic Binding addConsumerBinding(){return new Binding(addConsumerQueue, Binding.DestinationType.QUEUE,redundancyEventExchange,addConsumerBindingKey,null);}
}

🌟消息协议封装

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class EventMessage implements Serializable {/*** 消息队列id*/private String messageId;/*** 事件类型*/private String eventMessageType;/*** 业务id*/private String bizId;/*** 消息体*/private String content;/*** 异常备注*/private String remark;
}

🌟消息类型封装

public enum EventMessageTypeEnum {REDUNDANCY_ADD,REDUNDANCY_ADD_BUSINESS,REDUNDANCY_ADD_CONSUMER,REDUNDANCY_DEL,REDUNDANCY_DEL_BUSINESS,REDUNDANCY_DEL_CONSUMER,REDUNDANCY_UPDATE,REDUNDANCY_UPDATE_BUSINESS,REDUNDANCY_UPDATE_CONSUMER,
}

🌟C端消费者

@Component
@Slf4j
@RabbitListener(queuesToDeclare = {@Queue("redundancy.add.consumer.queue")})
public class RedundancyAddConsumerMQListener {@Autowiredprivate DetailService detailService;/*** 消费消息* @param eventMessage* @param message* @param channel*/@RabbitHandlerpublic void handleAddConsumer(EventMessage eventMessage, Message message, Channel channel){try {eventMessage.setEventMessageType(EventMessageTypeEnum.REDUNDANCY_ADD_CONSUMER.name());boolean flag= detailService.handleAddDetail(eventMessage);} catch (Exception e) {log.error("handleAddConsumer--消费失败{}",eventMessage);}}
}

🌟B端消费者

@Component
@Slf4j
@RabbitListener(queuesToDeclare = {@Queue("redundancy.add.business.queue")})
public class RedundancyAddBusinessMQListener {@Autowiredprivate DetailService detailService;/*** 消费消息* @param eventMessage* @param message* @param channel*/@RabbitHandlerpublic void handleAddBusiness(EventMessage eventMessage, Message message, Channel channel){try {eventMessage.setEventMessageType(EventMessageTypeEnum.REDUNDANCY_ADD_BUSINESS.name());boolean flag= detailService.handleAddDetail(eventMessage);} catch (Exception e) {log.error("handleAddBusiness--消费失败{}",eventMessage);}}
}

🌟发送消息与处理消息

   /*** 发送新增消息* @param detailRequest*/@Overridepublic void addDetail(DetailRequest detailRequest) {detailRequest.setBId(IDUtil.generateRandomNumber(5));detailRequest.setCId(IDUtil.generateRandomNumber(5));//构造消息EventMessage eventMessage = EventMessage.builder().messageId(IDUtil.generateRandomNumber(5).toString()).content(JsonUtil.obj2Json(detailRequest)).eventMessageType(EventMessageTypeEnum.REDUNDANCY_ADD.name()).build();rabbitTemplate.convertAndSend(rabbitMqForRedundancyConfig.getRedundancyEventExchange(),rabbitMqForRedundancyConfig.getAddRoutingkey(),eventMessage);}
//处理新增消息
@Overridepublic boolean handleAddDetail(EventMessage eventMessage) {String messageType= eventMessage.getEventMessageType();DetailRequest detailRequest=JsonUtil.json2Obj(eventMessage.getContent(), DetailRequest.class);if (messageType.equals(EventMessageTypeEnum.REDUNDANCY_ADD_CONSUMER.name())){CDetailDO cDetailDOIndb=cDetailMapper.selectOne(new QueryWrapper<CDetailDO>().eq("c_id",detailRequest.getCId()).eq("detail",detailRequest.getDetail()));if (cDetailDOIndb==null){CDetailDO cDetailDO = CDetailDO.builder().bId(detailRequest.getBId()).cId(detailRequest.getCId()).detail(detailRequest.getDetail()).build();cDetailMapper.insert(cDetailDO);}else {log.error("handleAddDetail---REDUNDANCY_ADD_CONSUMER重复{}",eventMessage);}} else if (messageType.equals(EventMessageTypeEnum.REDUNDANCY_ADD_BUSINESS.name())) {BDetailDO bDetailDOIndb=bDetailMapper.selectOne(new QueryWrapper<BDetailDO>().eq("b_id",detailRequest.getCId()).eq("detail",detailRequest.getDetail()));if (bDetailDOIndb==null){BDetailDO bDetailDO = BDetailDO.builder().bId(detailRequest.getBId()).cId(detailRequest.getCId()).detail(detailRequest.getDetail()).build();bDetailMapper.insert(bDetailDO);}else {log.error("handleAddDetail---REDUNDANCY_ADD_BUSINESS重复{}",eventMessage);}}return false;}

🌟最后

最后,感谢大家对本文的阅读,希望对大家有帮助。


请添加图片描述

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

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

相关文章

Linux 重启systemd 进程

当升级库文件后&#xff0c;那些使用该库的服务需要重启后才会真正使用该库文件中的内容。一个常用的方法是直接重启系统&#xff0c;这样所有服务在启动时自然使用的是最新库的内容&#xff0c;但是作为服务器是不可能允许随意重启的&#xff0c;那么在不重启的情况下如何找出…

将本地项目推送到github

欢迎大家到我的博客浏览。将本地项目推送到github | YinKais Blog 本地项目上传至 GitHub<!--more--> 1、进入项目根目录&#xff0c;初始化本地仓库 git init 2、创建密钥&#xff1a;创建 .ssh 文件夹&#xff0c;并进入 .ssh 文件夹 mkdir .ssh cd .ssh/ 3、生成…

关于 SLO,我们需要了解什么?

什么是 SLO&#xff1f; SLO&#xff08;Service Level Objective&#xff09;是服务质量目标的短语缩写。它通常指的是维护系统的最高级别的目标&#xff0c;或服务等级协议&#xff08;SLA&#xff09;中的服务质量目标。它能够定义客户和用户在使用软件系统时所期望的服务质…

基于ssh的盘锦河蟹销售系统

摘 要 如今&#xff0c;互联网时代的到来&#xff0c;在社会环境的带动下&#xff0c;各行各业都被科技的发展推着前进。提高了生活效率&#xff0c;越来越多行业已经实现了信息管理自动化&#xff0c;商品销售行业也不例外。如今伴随着5G互联网时代的来到&#xff0c;网上浏览…

云服务器anaconda(py39)+pytorch1.12.0(cu113)

用xshell连接ip地址&#xff0c;端口号22&#xff0c;输入用户密码 查看当前版本 conda -V conda info --envs 如果不是需要的版本&#xff0c;使用 anaconda-clean --yes rm -rf anaconda3 删除文件夹 安装anaconda 2022 10 py3.9 wget https://repo.anaconda.com/archi…

<Linux>(极简关键、省时省力)《Linux操作系统原理分析之存储管理(2)》(15)

[TOC](《Linux操作系统原理分析之存储管理&#xff08;2&#xff09;》&#xff08;15&#xff09; 5 存储管理5.4 分页存储管理5.4.1 纯分页存储管理a.页&#xff08;页面&#xff09;和物理块&#xff08;帧&#xff09;b. 页面大小c. 逻辑地址结构 5.5 存储扩充技术5.5.2 交…

用友NC 漏洞

漏洞描述 用友ERP-NC 存在目录遍历漏洞&#xff0c;攻击者可以通过目录遍历获取敏感文件信息。 fofa&#xff1a; poc&#xff1a;/NCFindWeb?serviceIPreAlertConfigService&filename 在url处拼接poc后可以看到该站点的目录和文件 访问某个文件 /NCFindWeb?serviceIPr…

一文搞懂微前端

一. 微前端的背景和动机 单页应用 单页应用往往是一个庞大的前端项目&#xff0c;由一个团队或多个团队共同开发&#xff0c;使用同一套技术栈&#xff0c;打包成一个整体&#xff0c;部署在一个域名下 随着 Web 应用的功能越来越丰富和复杂&#xff0c;单页应用不得不面临以下…

QMLfor python pyside6

QML QML是一种用于创建用户界面的声明性语言&#xff0c;它是Qt生态系统中的一部分。QML使用JavaScript语言和其独特的语法来定义用户界面组件&#xff0c;使得开发人员可以轻松地创建现代化、漂亮而又响应迅速的应用程序。 QML是基于QtQuick技术构建的&#xff0c;QtQuick是…

【JavaScript】3.4 JavaScript在现代前端开发中的应用

文章目录 1. 用户交互2. 动态内容3. 前端路由4. API 请求总结 JavaScript 是现代前端开发的核心。无论是交互效果&#xff0c;还是复杂的前端应用&#xff0c;JavaScript 都发挥着关键作用。在本章节中&#xff0c;我们将探讨 JavaScript 在现代前端开发中的应用&#xff0c;包…

上门服务系统|东郊到家软件提供高效服务的科技支柱

预约上门服务系统的崛起改变了传统服务行业的格局。用户不再需要亲自前往实体店面&#xff0c;而是通过几次点击就能享受到各类服务。这背后离不开预约上门服务系统的智能化和高效性&#xff0c;而源码正是这个系统的灵魂所在。下面小编就给大家介绍下上门服务系统开发优势。 1…

Gavin Wood:财库保守主义偏离了初心,应探索 Fellowship 等更有效的资金部署机制

波卡创始人 Gavin Wood 博士最近接受了 The Kusamarian 的采访&#xff0c;分享了他的过往经历、对治理的看法&#xff0c;还聊到了 AI、以太坊、女巫攻击、财库等话题。本文整理自 PolkaWorld 对专访编译的部分内容&#xff0c;主要包含了 Gavin 对治理、财库提案、生态资金分…

人工智能_机器学习056_拉格朗日乘子法原理推导_公式由来详解_原理详解---人工智能工作笔记0096

https://blog.csdn.net/Soft_Po/article/details/118332454 这里有老师的一篇文章介绍拉格朗日乘子法的原理推导 结合老师的这篇文章我们来看一下详细的推导过程 可以看到上一节我们说,一个有条件的,函数,可以转换为一个,无条件的函数, 根据拉格朗日乘子法,可以创建出一个等…

uc_09_创建新进程 exec() system()

1 什么是创建新进程(夺舍) 在前面文章中&#xff0c;我们学习了fork()函数用来创建子进程。 子进程是父进程的副本&#xff0c;复制父进程除代码段以外的其他数据&#xff0c;代码段数据和父进程共享。 子进程的PID与父进程不同&#xff1a; 而创建新进程则不同。 与fork()不同…

docker-compose;私有镜像仓库harbor搭建;镜像推送到私有仓库harbor

docker-compose&#xff1b;私有镜像仓库harbor搭建&#xff1b;镜像推送到私有仓库harbor 文章目录 docker-compose&#xff1b;私有镜像仓库harbor搭建&#xff1b;镜像推送到私有仓库harbordocker-compose私有镜像仓库harbor搭建镜像推送到私有仓库harbor docker-compose D…

论坛自动多播放源采集源码

论坛自动多播放源采集源码是一种用于自动抓取论坛中的多个视频播放源的程序源代码。它可以自动搜索并采集论坛中的多个视频播放源&#xff0c;帮助用户快速找到所需的视频资源。该源码可以帮助用户节省时间和精力&#xff0c;提高视频资源的获取效率。 演示 地 址&#xff1a;…

2023年小美赛认证杯A题太阳黑子预测(Sunspot Forecasting)思路模型代码解析

2023年小美赛认证杯A题&#xff1a;太阳黑子预测&#xff08;Sunspot Forecasting&#xff09; 【请电脑打开本文链接&#xff0c;扫描下方名片中二维码&#xff0c;获取更多资料】 一、问题重述 太阳黑子是太阳光球上的现象&#xff0c;呈暂时性斑点&#xff0c;比周围区域…

2023年中国金融科技研究报告

第一章 行业概况 1.1 定义 金融科技&#xff08;FinTech, Financial Technology&#xff09;代表了金融和技术的交汇。这一领域虽然处于发展的初期阶段&#xff0c;但已经展现出深远的影响力。金融科技的业务模式多样&#xff0c;涵盖了从传统金融服务的数字化转型到新兴技术…

python中的序列类型

文章目录 字符串列表元组由元组构成的列表 字符串 字符串是编程语言中的一种基本数据类型&#xff0c;用于表示一串字符序列。在Python中&#xff0c;字符串是不可变的&#xff0c;也就是说一旦字符串被创建&#xff0c;就无法修改其中的字符。 Python中的字符串可以用单引号…

索尼mxf覆盖部分恢复案例(索尼PMW-580)

索尼mxf覆盖部分恢复案例(索尼PMW-580) 索尼的摄像机型号是比较繁多的&#xff0c;高端系列基本上是以mxf文件为主&#xff0c;这一类案例之前处理不少&#xff0c;今天我们看一个索尼pmw-580摄像机删除后又覆盖的恢复案例。 故障存储:64G SD卡/Exfat文件系统 故障现象: 拍…