RabbitMQ死信交换机

目录

1.死信交换机介绍

 2.TTL

3.延迟队列

4.消息堆积问题

5.惰性队列

 6.代码实战


1.死信交换机介绍

当一个队列中信息满足下列情况之一时,可以成为死信(dead letter)

  (1)消费者使用basic.reject(RejectAndDontRequeueRecoverer处理策略)或bastic.nack(ImmediateRequeueMessageRecoverer处理策略)消费失败,requeue(重新入队)设置参数为false;

  (2)消息是一个过期消息,过期无人消费;

  (3)要投递的队列消息堆积满了,最早的消息成为死信;

如果该队列配置了dead-letter-exchange属性,指定交换机,队列设置dead-letter-routing-key属性,设置死信交换机与死信队列的RoutingKey,那么队列中的死信就会投递到这个交换机中,而这个交换机成为死信交换机(Dead Letter Exchange,简称DLX)。

 

 2.TTL

        TTL,也就是Time-To-Live。如果队列中的消息TTL结束仍未消费则会成为死信,TTL超时分为两种情况:

  (1)消息所在的队列设置了存活时间;

  (2)消息本身设置了存活时间;

 

3.延迟队列

利用ttl结合死信交换机,实现了消息发出后,消费者延迟收到消息的结果,这种消息队列成为延迟队列(Delay Queue)模式。

延迟队列使用的场景:

  (1)用户下单后超过15分钟未支付取消支付;

  (2)预约20分钟会议,到时间自动通知参会人员;

订单的超时处理:

生产者生产一条1分钟后超时的订单消息到正常交换机exchange中,但一分钟后仍未消费,消息会被投递到死信交换机dlx-exchange中,并发送到私信队列中,死信队列dlx-queue的消费者拿到消息后,根据消息去查询订单的状态,如果仍然是为支付状态,将订单状态更新为超时状态 

4.消息堆积问题

当生产者发送的消息的速度大于消费者消费的速度,就会导致队列中的消息堆积,直到达到消息的上限,最早接受的消息,可能会被丢弃,成为死信。

解决消费堆积的三种策略:

  (1)增加消费者,增加消费速度

  (2)在消费者内开启线程池加快消息处理速度

  (3)扩大队列的容积

5.惰性队列

从RabbitMq的3.6.0版本开始增加了Lazy Queues的概念,也就是惰性队列。

惰性队列的特征如下:

  (1)接受消息后直接存入磁盘而非内存;

  (2)消费者消费消息才会中磁盘中将消息加载到内存;

  (3)支持数百万的数据存储;

 6.代码实战

先写两个队列和分别自定义一个直连交换机 并且给交换机分别绑定一个队列

    //死信,延迟队列
    @Bean
    public Queue queueA(){
        Map<String, Object> config = new HashMap<>();
        //message在该队列queue的存活时间最大为20秒
        config.put("x-message-ttl", 20000);
        //x-dead-letter-exchange参数是设置该队列的死信交换器(DLX)
        config.put("x-dead-letter-exchange", "ExchangeB"); 
        //x-dead-letter-routing-key参数是给这个DLX指定路由键
        config.put("x-dead-letter-routing-key", "bb");
        return new Queue("queueA",true,false,false,config);
    }
    @Bean
    public DirectExchange ExchangeA(){
        return new DirectExchange("ExchangeA");
    }
    @Bean
    public Binding bindingA(){
        return BindingBuilder.bind(queueA()).to(ExchangeA()).with("aa");
    }

    @Bean
    public Queue queueB(){
        return new Queue("queueB");
    }
    @Bean
    public DirectExchange ExchangeB(){
        return new DirectExchange("ExchangeB");
    }
    @Bean
    public Binding bindingB(){
        return BindingBuilder.bind(queueB()).to(ExchangeB()).with("bb");
    }

 在控制类给交换机发送一条消息

    //死信交换机
    @RequestMapping("/send5")
    public String send5(){
        template.convertAndSend("ExchangeA","aa","4502520");
        return "😡";
    }

写一个测试类进行测试

package com.example.consumer;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
@SuppressWarnings("all")
@Slf4j
@RabbitListener(queues="queueB")
public class ReceiverQB {
    @RabbitHandler
    public void process(String id){
        log.warn("QB接收到:" + id);
    }
}

 接着启动生产者和消费者,并在RabbitMQ中查看

 

注意:如果在启动消费者时报错,请先在页面上访问,再重新启动消费者 

因为我们设置队列queue的存活时间最大为20秒,所以再隔20秒后消息会自动出来

 

 

确认消息(局部方法处理消息)

默认情况下消息消费者是自动 ack (确认)消息的,如果要手动 ack(确认)则需要修改确认模式为 manual

在消费者的yml文件中进行配置

server:
    port: 9999
spring:
    rabbitmq:
        host: 192.168.169.132
        password: 123456
        port: 5672
        username: spring
        virtual-host: my_vhost
        listener:
            simple:
                acknowledge-mode: manual
接着写一个测试类
package com.example.consumer;

import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.boot.autoconfigure.amqp.RabbitProperties;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;

@Component
@SuppressWarnings("all")
@Slf4j
@RabbitListener(queues="queueA")
public class ReceiverQA {
    @RabbitHandler
    public void process(String id, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long tag) throws Exception{
        log.warn("QA接收到:" + id);
        channel.basicAck(tag,true);

    }
}

在页面中刷新上面的方法,可以在idea中看到

如果想要手动否认,拒绝消息

@RabbitHandler
    public void process(String id, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long tag) throws Exception{
        log.error("QA接收到:" + id);
        channel.basicReject(tag,true);
        Thread.sleep(1000);//延迟时间
    }

因为延迟时间只有1秒钟,而且需要重新进入队列,所以会一直循环,在循环到在我们上面设置的那个20秒钟后会进入QB

也可以拒绝该消息,消息会被丢弃,不会重回队列  

    @RabbitHandler
    public void process(String id, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long tag) throws Exception{
        log.error("QA接收到:" + id);
        channel.basicReject(tag,false);
        Thread.sleep(1000);//延迟时间
    }

这时候会直接进入QB 

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java基础进阶02-xml

目录 一、XML&#xff08;可拓展标记语言&#xff09; 1.学习网站&#xff1a; 2.作用 3.XML标签 4.XML语法 5.解析XML &#xff08;1&#xff09;常见解析思想DOM 6.常见的解析工具 7.DOM4j的使用 8.文档约束 &#xff08;1&#xff09;概述 &#xff08;2&#xf…

全桥变压器计算1

一共有两级&#xff0c;先DC升压&#xff0c;后H桥逆变为AC 因为两级都有损耗&#xff0c;所以一般用输入功率计算 电池升压到400V高压用的效率用表示&#xff0c;后面DC转AC的效率用表示&#xff0c;输入电压用Vin&#xff0c;输出功率Po2000W,输入功率为Pin 一般和96% 所…

Pandas ------ 向 Excel 文件中写入含有 multi-index 和 Multi-column 表头的数据

Pandas ------ 向 Excel 文件中写入含有 multi-index 和 Multi-column 表头的数据 引言正文 引言 之前在 《pandas向已经拥有数据的Excel文件中添加新数据》 一文中我们介绍了如何通过 pandas 向 Excel 文件中写入数据。那么对于含有多表头的数据&#xff0c;我们该如何将它们…

单调性的应用

1单调性 应用场景&#xff1a;常应用于双指针的进一步优化问题中含义&#xff1a;针对指针 i 1 > i i1>i i1>i一定有 j 1 > j j1>j j1>j或者 j 1 < j j1<j j1<j这样我们就可以利用该性质对算法进行进一步优化&#xff0c;避免一些不必要的遍历…

Linux——系统简介

1、从UNIX到LINUX 在目前主流的服务器端操作系统中&#xff0c;UNIX诞生于20世纪60年代末&#xff0c;Windows诞生于20世纪80年代中期&#xff0c;Linux诞生于20世纪90年代初&#xff0c;可以说UNIX是操作系统中的“老大哥”。 1.1、Linux简史 Linux内核最初是由李纳斯托瓦兹…

Caused by: com.mongodb.MongoTimeoutException: Timed out after 30000 ms

报错 Caused by: com.mongodb.MongoTimeoutException: Timed out after 30000 ms while waiting to connect. Client view of cluster state is {typeUNKNOWN, servers[{addressmangodb-m.cc.com:3717, typeUNKNOWN, stateCONNECTING, exception{com.mongodb.MongoSocketReadE…

java数据结构与算法刷题-----LeetCode769. 最多能完成排序的块

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 解题思路 这道题可以理解为&#xff0c;只能保证块内有序的情况下&#xf…

力扣日记1.25-【回溯算法篇】39. 组合总和

力扣日记&#xff1a;【回溯算法篇】39. 组合总和 日期&#xff1a;2023.1.25 参考&#xff1a;代码随想录、力扣 39. 组合总和 题目描述 难度&#xff1a;中等 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target &#xff0c;找出 candidates 中可以使数字和…

【域名解析】如何将域名指向对应服务器IP

目录 &#x1f337;一、域名解析基本概念 &#x1f33c;1. 定义 &#x1f33c;2. 域名解析类型 &#x1f337;二、域名解析服务器IP地址 &#x1f33c;1. 操作步骤 &#x1f33c;2. 验证 &#x1f337;一、域名解析基础知识 &#x1f33c;1. 基本概念 定义&#xff1a; …

微信小程序开发scroll-view在预览或真机调试仅显示第一个元素解决方案

现象如下&#xff1a; 在编译时显示正常&#xff1a; 在预览或真机调试时仅显示第一个元素&#xff1a; 解决方案&#xff1a;将app.json文件中renderer类型由skyline改为webview 更多微信小程序内容欢迎关注我&#xff01; 有帮助的话欢迎打赏&#xff01;

二次开发RuoYi-Vue操作记录

二次开发RuoYi-Vue操作记录 一、本地启动修改1、修改文件路径2、修改redis配置3、数据源配置4、导入sql 二、新增模块1、创建模块2、添加依赖 三、新增页面1、数据准备2、代码生成3、菜单管理&#xff08;1&#xff09;目录创建&#xff08;2&#xff09;菜单创建&#xff08;3…

ESP32开发板可以承受的最大电压

ESP32的最大工作电压为3.3V。但这并不意味着我们不能向 ESP32开发板施加大于 3.3V 的电压。ESP32 具有板载稳压器&#xff0c;使用 VIN 和 GND 引脚可承受最大 15V 的电压。 一旦电压输入到 ESP32 开发板VIN 引脚&#xff0c;该电压就会通过 ESP32 板载稳压器&#xff08;AMS11…

宏景eHR SmsAcceptGSTXServlet XXE漏洞复现

0x01 产品简介 宏景eHR人力资源管理软件是一款人力资源管理与数字化应用相融合,满足动态化、协同化、流程化、战略化需求的软件。 0x02 漏洞概述 宏景eHR SmsAcceptGSTXServlet接口处存在XML实体注入漏洞,未经身份认证的攻击者可以利用此漏洞读取系统内部敏感文件,获取敏…

群辉NAS的远程访问

群辉NAS是私有云存储&#xff0c;局域网访问很容易【详见&#xff1a;网上邻居访问设置、其它设备的访问设置】&#xff0c;远程访问相对复杂&#xff0c;涉及很多关键因素&#xff0c;现将过程记录如下&#xff1a; 目录 1、互联网接入 2、绑定MAC与IP地址 3、路由器开启5…

qml中访问控件内部的子项

如何访问Repeater类型内部的子项、Row等布局类型内部的子项以及ListView内部的子项等。。。 1、测试代码 import QtQuick 2.0 import QtQuick.Controls 2.12 import QtQuick.Window 2.12 import QtQuick.Layouts 1.3 import QtQml 2.12Window {id: windowobjectName: "m…

米贸搜|Facebook“精准营销”越来越难?或许是“受众定位”没彻底搞清!

一、为何要确定目标受众 对于每个广告主而言&#xff0c;面向最有可能成为其客户的用户营销非常重要&#xff0c;因此&#xff0c;确定目标受众&#xff0c;是Facebook广告投放中极其重要的一环。 二、什么是目标受众&#xff1f; 目标受众是您希望向其传达营销信息&#xf…

java servlet 高校田径运动会管理系统Myeclipse开发mysql数据库web结构jsp编程计算机网页项目

一、源码特点 jsp高校田径运动会管理系统是一套完善的java web信息管理系统 采用mvc模式 servletdaobean 模式开发&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myecl…

“JavaScript 循环中的 ‘await‘

目录 前言 for使用await -- 有效的 forEach使用await -- 无效的 for of 使用await 有效的 for await of 使用await 有效的 总结 前言 在JavaScript的forEach方法中使用await是无效的&#xff0c;因为forEach方法不支持异步操作的等待。 forEach是一个数组的遍历方法&…

如何修改hosts文件-mac

1、什么是hosts文件&#xff1f; Hosts是一个没有扩展名的系统文件&#xff0c;可以用记事本等工具打开&#xff0c;其作用就是将一些常用的网址域名与其对应的IP地址建立一个关联“数据库”&#xff0c;即域名映射到IP地址&#xff0c;域名是为了方便人类记忆识别&#xff0c…

力扣354. 俄罗斯套娃信封问题

动态规划 思路&#xff1a; 同时控制 w、h 两个维度比较复杂&#xff0c;可以先固定一个维度&#xff0c;来找出另外一个维度的严格单调序列&#xff1a; 对 w 排序&#xff0c;然后再来找 h 维度严格单调递增序列长度&#xff1b;在 w 排序时&#xff0c;会遇到 w(i) w(j) 的…