RabbitMq之发布确认(高级)

news2024/11/17 4:26:58

一.发送消息到交换机失败

正常情况下生产者只发布消息到交换机,无法确定是否成功把消息发送到交换机当中,由此发布确认的回调函数可以通知生产者消息是否发送到了交换机。
在这里插入图片描述

代码如下
1.先创建交换机、队列等信息

package jot.jothot.testMq;

import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 发布确认高级
 */
@Configuration
public class ConfirmConfig {

    //交换机
    public static final String CONFIRM_EXCHANGE_NAME= "confirm_exchange";
    //队列
    public static final String CONFIRM_QUEUE_NAME= "confirm_queue";
    //routingKey
    public static final String CONFIRM_ROUTING_NAME= "confirm_key";

    @Bean("confirmExchange")
    public DirectExchange directExchange(){
        return new DirectExchange(CONFIRM_EXCHANGE_NAME);
    }

    @Bean("confirmQueue")
    public Queue confirmQueue(){
        return QueueBuilder.durable(CONFIRM_QUEUE_NAME).build();
    }

    @Bean
    public Binding queueBindingExchange(@Qualifier("confirmExchange")DirectExchange directExchange,
                                        @Qualifier("confirmQueue")Queue confirmQueue){
        return BindingBuilder.bind(confirmQueue).to(directExchange).with(CONFIRM_ROUTING_NAME);
    }
}

2.创建消费者

package jot.jothot.testMq;

import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.util.Date;

@Slf4j
@Component
public class ReceiveMessage {

    @RabbitListener(queues = ConfirmConfig.CONFIRM_QUEUE_NAME ,containerFactory = "rabbitListenerContainerFactory")
    public void receiveMessage(Message message, Channel channel) throws Exception {
        // 处理消息
        String msg = new String(message.getBody());
        log.info("当前时间:{},收到发布确认高级队列的消息:{}",new Date().toString(),msg);
    }
}

3.编写回调接口

package jot.jothot.testMq;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

/**
 * 回调实现类
 */
@Slf4j
@Component
public class MyCallBack implements RabbitTemplate.ConfirmCallback {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 1、MyCallBack 实现了接口 RabbitTemplate.ConfirmCallback,注意 ConfirmCallback
     *   是 RabbitTemplate 类中的一个内部接口,所以在实现 RabbitTemplate.ConfirmCallback 接口后,
     *   还需要将其注入到 RabbitTemplate 的实例当中。
     * 2、标有 @PostConstruct 注解的方法,容器在 bean 创建完成并且属性赋值完成后,会调用该初始化方法。
     */
    @PostConstruct
    public void init(){
        rabbitTemplate.setConfirmCallback(this);
    }

    /**
     * 交换机不管是否接收到消息都会回调该方法
     *
     * @param correlationData 保存回调消息的ID及相关信息,由消息生产者确定,如果消息生产者未明确定义CorrelationData,则此处为null
     * @param ack ack=true/false true表示收到消息,false表示未收到消息
     * @param cause 若接收消息成功,则为null;若接收消息失败,则为失败的原因
     */
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        String id = correlationData !=null ? correlationData.getId():"";
        if(ack){
            log.info("交换机已经收到消息ID为{}的消息",id);
        }else {
            log.info("交换机未经收到消息ID为{}的消息由于原因{}",id,cause);
        }
    }
}

4.配置文件中配置publisher-confirm-type

  rabbitmq:
     host: 192.168.126.130
     port: 5672
     username: root
     password: 123456
     publisher-confirm-type: correlated #发布确认模式属性

publisher-confirm-type属性如下
1.NONE:禁用发布确认模式,是默认值
2.CORRELATED:发布消息成功到交换器后会触发回调方法
3.SIMPLE:有两种效果。一是和 CORRELATED 一样会触发回调方法;二是在发布消息成功后使用 rabbitTemplate 调用 waitForConfirms 或 waitForConfirmsOrDie 方法,等待 broker 节点返回发送结果,根据返回结果来判定下一步的逻辑。要注意的点是 waitForConfirmsOrDie 方法如果返回 false 则会关闭 channel,回导致接下来无法发送消息到 broker。
5.生产者

@PostMapping("/sendMsg")
    public void sendMsg(String message){
        CorrelationData correlationData = new CorrelationData("1");
        //给正确交换机发送消息
        rabbitTemplate.convertAndSend(ConfirmConfig.CONFIRM_EXCHANGE_NAME,ConfirmConfig.CONFIRM_ROUTING_NAME,message,correlationData);
        //给错误交换机发送消息
        rabbitTemplate.convertAndSend("xx",ConfirmConfig.CONFIRM_ROUTING_NAME,message,correlationData);
        log.info("当前时间:{},发送一条信息给队列:{}",new Date().toString(),message);
    }

启动项目调用接口显示如下
在这里插入图片描述

二.回退消息

交换机把消息推送到队列失败,也需要通知生产者消息发送失败
在这里插入图片描述
1.基于上面的代码,在回调类中实现回退接口

package jot.jothot.testMq;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.ReturnedMessage;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

/**
 * 回调实现类
 */
@Slf4j
@Component
public class MyCallBack implements RabbitTemplate.ConfirmCallback,RabbitTemplate.ReturnsCallback {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 1、MyCallBack 实现了接口 RabbitTemplate.ConfirmCallback,注意 ConfirmCallback
     *   是 RabbitTemplate 类中的一个内部接口,所以在实现 RabbitTemplate.ConfirmCallback 接口后,
     *   还需要将其注入到 RabbitTemplate 的实例当中。
     * 2、标有 @PostConstruct 注解的方法,容器在 bean 创建完成并且属性赋值完成后,会调用该初始化方法。
     */
    @PostConstruct
    public void init(){
        //注入接口
        rabbitTemplate.setConfirmCallback(this);
        //注入消息回退接口
        rabbitTemplate.setReturnsCallback(this);
    }

    /**
     * 交换机不管是否接收到消息都会回调该方法
     *
     * @param correlationData 保存回调消息的ID及相关信息,由消息生产者确定,如果消息生产者未明确定义CorrelationData,则此处为null
     * @param ack ack=true/false true表示收到消息,false表示未收到消息
     * @param cause 若接收消息成功,则为null;若接收消息失败,则为失败的原因
     */
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        String id = correlationData !=null ? correlationData.getId():"";
        if(ack){
            log.info("交换机已经收到消息ID为{}的消息",id);
        }else {
            log.info("交换机未经收到消息ID为{}的消息由于原因{}",id,cause);
        }
    }

    /**
     * 消息回退接口
     * @param returned
     */
    @Override
    public void returnedMessage(ReturnedMessage returned) {
        log.error("消息{},被交换机{}退回,退回的原因:{},路由key:{}",returned.getMessage(),returned.getExchange(),returned.getReplyText(),returned.getRoutingKey());
    }
}

2.修改RabbitMq配置文件

 rabbitmq:
     host: 192.168.126.130
     port: 5672
     username: root
     password: 123456
     publisher-confirm-type: correlated #发布确认模式属性
     publisher-returns: true #开启回退消息

3.生产者发送错误的RoutingKey

@PostMapping("/sendMsg")
    public void sendMsg(String message){
        CorrelationData correlationData = new CorrelationData("1")
        //错误队列发送消息
        rabbitTemplate.convertAndSend(ConfirmConfig.CONFIRM_EXCHANGE_NAME,"ConfirmConfig.CONFIRM_ROUTING_NAME",message,correlationData);
        log.info("当前时间:{},发送一条信息给队列:{}",new Date().toString(),message);
    }

演示结果如下
在这里插入图片描述
完整错误信息

消息(Body:'发布确认' MessageProperties [headers={spring_returned_message_correlation=1}, contentType=text/plain, 
contentEncoding=UTF-8, contentLength=0, receivedDeliveryMode=PERSISTENT, priority=0, deliveryTag=0]),
被交换机confirm_exchange退回,退回的原因:NO_ROUTE,路由key:ConfirmConfig.CONFIRM_ROUTING_NAME

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

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

相关文章

OS 学习笔记(6) 操作系统引导

OS 学习笔记(6) 操作系统引导 这篇笔记对应的王道OS 1.5 操作系统引导,同时参考了 《Operating System Concepts, Ninth Edition》和 俗称ostep的《 Operating Systems: Three Easy Pieces》还有 《Operating Systems: Principles and Practice》 文章目录OS 学习笔…

实战还原--从大黄蜂样本到域控管理员技术解析

0 前言实战案例还原《BumbleBee Roasts Its Way To Domain Admin》一文详细的描述了一次渗透案例,但其文章组织架构建立在ATT&CK框架上,而不是按照时间线逻辑来组织,因此对于渗透人员了解学习其前后过程有些困难,特此梳理一番…

发布微信小程序获取收集用户信息权限

前言在发布微信小程序的时候我们经常会遇到审核不通过的情况,其中一种特别让我头疼就是说小程序收集、使用和储存用户信息。不给予通过。但是他们的接口又不能提供这个功能,并且老是改动,真的特别的麻烦加无语。有时候审核偷一下懒&#xff0…

算法刷题-回文数、找出小于平均值的数、旋转图像(C_C++)

文章目录回文数找出小于平均值的数旋转图像回文数 给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。 回文数是指正序(从左向右)和倒序(从右向左)读都是一样的…

光电耦合器和MOSFET之间的差异

光电耦合器和MOSFET之间的差异 介绍 光电耦合器/光耦合器和固态继电器(光电MOSFET或光耦MOSFET(OCMOS FET))在保持电隔离的同时传输信号,但存在一些重要差异。 结构差异 下图显示了光电耦合器和OCMOS FET的主要内部…

Vue实战第2章:简单的分配页面布局

缓冲 前言 本篇在讲什么 本篇作为Vue实战的第二章,跟代码逻辑无关,主要是简单的先设计一下个人网站的各个模块内容,明确一下我们想要将网站做出什么样子 本篇的特色 具有全流程的图文教学 重实践,轻理论,快速上…

趣味三角——第6章——两个几何定理

第6章 两个几何定理 It is the glory of geometry that from so few principles, fetched from without, it is able to accomplish so much. (几何学的荣耀在于,仅从几个原理出发,外求于无物,但却能够完成如此非凡的壮举。) ——Isaac N…

linux基本功系列-top命令实战

文章目录一. top命令介绍二. 语法格式及常用选项三. 参考案例3.1 显示进程信息3.2 显示完整的进程命令3.3 以批处理的形式展示3.4 设置信息更新频次3.5 显示指定进程号的信息3.6 top面板中常用参数3.7 其他用法四. top的相关说明4.1 交互命令介绍4.2 top面板每行信息的含义4.2.…

MySQL(八):事务的隔离级别、MVCC的原理

目录一、事务的隔离级别1.1 事务的隔离性1.2 事务并发执行引发的一致性问题1.2.1 脏写1.2.2 脏读1.2.3 不可重复读1.2.4 幻读1.3 SQL标准中的四种隔离级别1.4 MySQL中支持的4中隔离级别二、MVCC原理2.1 版本链2.2 ReadView2.3 READ COMMITED 每次读取数据前都生成一个ReadView2…

使用独立显卡安装黑苹果,但无法扩展显示器的解决方案

使用独立显卡安装黑苹果,但无法扩展显示器的解决方案 网上的教程 本文的外部链接🔗 引用文中的一句话:“这也许是无法驱动独显的黑苹果笔记本想要外接显示器的唯一方案。” ---- 购买拥有displaylink的外置显卡的usb转接器 文章作者给我了…

word@菜单自定义和公式输入

菜单栏快捷键设置 word 设置(选项) Word options (General) - Microsoft Support 点击文件->选项 自定义word菜单 自定义功能区 Customize the ribbon in Word - Microsoft Support Customizing the source list of commandsThe ribbon listAdd or remove commandsReor…

[golang Web开发] 2.golang web开发:操作数据库,增删改查,单元测试

简介 Go 语言中的 database/sql包定义了对数据库的一系列操作,database/sql/driver包定义了应被数据库驱动实现的接口,这些接口会被sql包使用.但是 Go语言没有提供任何官方的数据库驱动,所以需要导入第三方的数据库驱动,不过连接数据库之后对数据库操作的…

超经典JavaIDEA 10个插件 Java开发工程师

工欲善其事,必先利其器。 作为一名合格的程序员,合理配置我们所用的IDEA,是高效开发的必修课。而如今的插件工具也越来越好用,不仅基本具备了智能提示,还可以自动补全代码,甚至能够在查出bug的同时提供修改…

如何彻底删除硬盘数据?电脑高手也恢复不了

实用的小命令,就是彻底删除硬盘上的数据,硬盘恢复软件也恢复不了! 1.以管理员身份运行cmd窗口,打开cmd,如下图所示: 2.在命令提示窗口中,直接输入cipher /w:路径,输入这个命令加上路径即可将文件彻底删除! 可以从整个命令说明上看到是从整个卷上可用的未使用磁盘空间…

Git (2) :Git练习--分支的新建与合并

一.首先有个问题 ? 在进行git练习前,有个问题需要提下。。。。 csdn无法登录了。 查了一下资料,是因为CSDN服务器的各地相应速度不一样,辽宁的响应是超时的,所以通过在hosts文件中指定域名http://csdnimg.cn的服务器…

机器学习之卷积操作

很多好主意一旦踏上语义鸿沟,就再也听不到。 卷积,在图像、视觉领域乃老生常谈的内容,但是对于具体工作细节仍然值得我去学习。 卷积原理 卷积,就是利用一个小的矩阵(或者更高维向量)作用于图像矩阵(或者特征矩阵),然…

Web测试、APP测试常用技巧(错过你一定会后悔)

目录 1. web元素定位七种方式 2. app元素定位3种方式 3. adb常用命令 4. 键盘操作常用函数 5. 鼠标操作常用函数 6. apppium: 7. fixture 1. web元素定位七种方式 优先使用的6种 find_element_by_id (返回一个元素)find_element(s)_by_class_name (根据类名…

2023-02-01 pthread线程局部数据-记录

摘要: pthread线程局部数据-记录 参考: https://www.akkadia.org/drepper/tls.pdf https://en.wikipedia.org/wiki/Thread-local_storage https://download.csdn.net/download/adofsauron/87408865 测试代码: 示例一: #include<stdio.h> #include<stdlib.h> #…

pip install timeout错误解决方案

大家好&#xff0c;我是爱编程的喵喵。双985硕士毕业&#xff0c;现担任全栈工程师一职&#xff0c;热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。喜欢通过博客创作的方式对所学的知识进行总结…

java spring Bean生命周期

首先 要搞清楚大概念 什么是生命周期&#xff1f; 学过vue和react的前端会有概念 简单说 就是一个对象从创建到销毁的整个过程 那么 bean的生命周期 我们先文字描述 然后再看效果 第一 阶段 通过构造器创建bean实例 就是找到bean对象配置的 类中的无惨构造 创建对象 第二阶段…