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

news2024/11/28 10:33:26

🧑‍💻作者名称: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
     */
    @Bean
    public Exchange redundancyEventExchange(){
        return new TopicExchange(redundancyEventExchange);
    }

    /**
     * 创建B端添加队列
     * @return
     */
    @Bean
    public Queue addBusinessQueue(){
        return new Queue(addBusinessQueue,true,false,false);
    }

    /**
     * 创建C端添加队列
     * @return
     */
    @Bean
    public Queue addConsumerQueue(){
        return new Queue(addConsumerQueue,true,false,false);
    }
    /**
     * B端绑定关系
     */
    @Bean
    public Binding addBusinessBinding(){
        return new Binding(addBusinessQueue, Binding.DestinationType.QUEUE,redundancyEventExchange,
                addBusinessBindingKey,null);
    }

    /**
     * C端交换机绑定到队列
     * @return
     */
    @Bean
    public 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 {
    @Autowired
    private DetailService detailService;
    /**
     * 消费消息
     * @param eventMessage
     * @param message
     * @param channel
     */
    @RabbitHandler
    public 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 {
    @Autowired
    private DetailService detailService;
    /**
     * 消费消息
     * @param eventMessage
     * @param message
     * @param channel
     */
    @RabbitHandler
    public 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
     */
    @Override
    public 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);
    }
//处理新增消息
@Override
    public 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.coloradmin.cn/o/1295785.html

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

相关文章

12.6每日一题(备战蓝桥杯程序的控制结构)

12.6每日一题&#xff08;备战蓝桥杯程序的控制结构&#xff09; 题目 1638: 【入门】判断正负数或零题目描述输入输出样例输入样例输出来源/分类 题解 1638: 【入门】判断正负数或零题目 1348: 【入门】求绝对值题目描述输入输出样例输入样例输出来源/分类 题解 1348: 【入门】…

【教学类-35-05】17号的学号字帖(A4竖版1份)

作品展示&#xff1a; 背景需求&#xff1a; 大四班17号男孩目前无法自主数学数字。他表示自己能够认识数字&#xff0c;但不会写。 保育老师说&#xff1a;我曾经教过他&#xff0c;抓着手示范的。但是他记不住。家里估计也不练习的。年龄还没到&#xff0c;下学期再看看能不…

SpringBoot项目访问resources下的静态资源

1.新建一个配置文件夹&#xff0c;放配置类 2.编辑 WebMvcConfig.java package com.southwind.configuration;import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import or…

期末速成数据库极简版【查询】(2)

目录 select数据查询----表 【1】筛选列 【2】where简单查询 【3】top-n/distinct/排序的查询 【4】常用内置函数 常用日期函数 常用的字符串函数 【5】模糊查询 【6】表数据操作——增/删/改 插入 更新 删除 【7】数据汇总 聚合 分类 ​ &#x1f642;&#…

2.6 A 的 LU 分解

一、A LU 线性代数很多关键的概念实际上就是矩阵的分解&#xff08;factorization&#xff09;。原始矩阵 A A A 变成两个或三个特殊矩阵的乘积。第一个分解&#xff0c;实际上也是最重要的分解&#xff0c;来自消元法。因子 L L L 和 U U U 都是三角形矩阵&#xff0c;分…

自动化测试:PO模式详解!

PO&#xff08;Page Object&#xff09;模式是一种在自动化测试中常用的设计模式&#xff0c;将页面的每个元素封装成一个对象&#xff0c;通过操作对象来进行页面的交互。 概括来说就是&#xff0c;每个页面都有对应的PO类&#xff0c;PO类中包含了页面的元素定位和操作方法。…

ArkTS语言难吗?鸿蒙指南

HarmonyOS的开发语言是ArkTS、JS(JavaScript)。 ArkTS简介 ArkTS是HarmonyOS优选的主力应用开发语言。ArkTS围绕应用开发在TypeScript&#xff08;简称TS&#xff09;生态基础上做了进一步扩展&#xff0c;继承了TS的所有特性&#xff0c;是TS的超集。因此&#xff0c;在学习…

c语言-动态内存管理

文章目录 一、为什么会有动态内存管理二、申请内存函数1、malloc2、free3、calloc4、realloc 三、常见的动态内存的错误四、练习 一、为什么会有动态内存管理 1.我们一般的开辟空间方式&#xff1a; int a 0;//申请4个字节空间 int arr[10] { 0 };//申请40个字节空间2.这样…

如何运用gpt改写出高质量的文章 (1)

大家好&#xff0c;今天来聊聊如何运用gpt改写出高质量的文章 (1)&#xff0c;希望能给大家提供一点参考。 以下是针对论文重复率高的情况&#xff0c;提供一些修改建议和技巧&#xff1a; 如何运用GPT改写出高质量的文章 一、引言 随着人工智能技术的飞速发展&#xff0c;自然…

QT 重定向qdebug输出到自绘界面

因为在嵌入式中调试qt需要查看输出信息,特意写了一个类用户便捷查看qdebug信息 界面如下: 提供了开始,停止,保存,清空,退出功能,具体代码下文给出 文件如下 #ifndef QDEBUGREDIRECT_H #define QDEBUGREDIRECT_H /**qdebug 重定向类 定向到界面控件*李吉磊 2023.12.7* */#in…

vue2中使用jsplumb完成流程图

前言 之前的几个demo都是在vue3中写的,虽然可以直接拿去复用。 但是根据有些看客反馈,想用一个vue2版本的,毕竟很多人开发功能的时间都不是特别富裕。大多时候还是用现成的demo更好一些。 这里我就写一个简易版本的demo,可以实现绘制,并且删除连接线和节点等功能,篇幅也不大…

麻雀1号开发板开箱

麻雀1号是上海睿赛德电子科技有限公司全新推出的一款高性价比音频Wi-Fi开发板&#xff0c;内置RT-Thread&#xff0c;主打 Wi-Fi、音频和摄像头拍照功能&#xff0c;配合丰富的组件及例程&#xff0c;可降低多媒体应用的开发门槛。 开发板介绍 正面&#xff1a; 背面&#x…

手搓图片滑动验证码_JavaScript进阶

手搓图片滑动验证码 背景代码效果图展示网站 背景 在做前端项目开发的时候&#xff0c;少不了登录注册部分&#xff0c;既然有登录注册就少不了机器人验证&#xff0c;验证的方法有很多种&#xff0c;比如短信验证码、邮箱验证码、图片滑动、图片验证码等。 由于鄙人在开发中…

docker安装与详细配置redis

docker安装redis 连接虚拟机 vagrant up //启动虚拟机 vagrant ssh //连接虚拟机进入root用户 su root输入密码&#xff1a;和账户名一样 vagrant 下载redis 直接下载redis镜像,下载redis最新镜像 docker pull redis下载的都是DockerHub中默认的官方镜像 创建文件目…

golang slice 数组针对某个字段进行排序

这里主要用到golang的sort.Sort方法&#xff0c;先看这个函数的简介&#xff1a; 介绍链接&#xff1a;https://books.studygolang.com/The-Golang-Standard-Library-by-Example/chapter03/03.1.html 如何实现&#xff1a; import "sort"// UserInfo 用户信息结构…

Bionorica成功完成SAP S/4HANA升级 提升医药制造业务效率

企业如何成功地将其现有的ERP ECC系统转换升级到SAP S/4HANA&#xff0c; 并挖掘相关潜力来推动其数字化战略&#xff1f;Bionorica应用SNP软件实施了实时ERP套件&#xff0c;为进一步的增长和未来的创新奠定了基础。 草药市场的领导者&#xff1a;Bionorica Bionorica是世界领…

.NET使用分布式网络爬虫框架DotnetSpider快速开发爬虫功能

前言 前段时间有同学在微信群里提问&#xff0c;要使用.NET开发一个简单的爬虫功能但是没有做过无从下手。今天给大家推荐一个轻量、灵活、高性能、跨平台的分布式网络爬虫框架&#xff08;可以帮助 .NET 工程师快速的完成爬虫的开发&#xff09;&#xff1a;DotnetSpider。 注…

Java实现屏幕截图程序(一)

在Java中&#xff0c;可以使用Robot类来实现屏幕截图程序。Robot类提供了一组用于生成输入事件和控制鼠标和键盘的方法。 Java实现屏幕截图的步骤如下&#xff1a; 导入Robot类 import java.awt.Robot;创建Robot对象 Robot robot new Robot();获取屏幕分辨率信息 Dimensi…

力扣面试题 08.12. 八皇后(java回溯解法)

Problem: 面试题 08.12. 八皇后 文章目录 题目描述思路解题方法复杂度Code 题目描述 思路 八皇后问题的性质可以利用回溯来解决&#xff0c;将大问题具体分解成如下待解决问题&#xff1a; 1.以棋盘的每一行为回溯的决策阶段&#xff0c;判断当前棋盘位置能否放置棋子 2.如何判…

JavaScript <关于逆向RSA非对称加密算法的案例(代码剖析篇)>--案例(五点一)

引用上文: CSDNhttps://mp.csdn.net/mp_blog/creation/editor/134857857 剖析: var bitsPerDigit16; // 每个数组元素可以表示的二进制位数// 数组复制函数&#xff0c;将源数组部分复制到目标数组的指定位置 function arrayCopy(src, srcStart, dest, destStart, n) {var m…