作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO
联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬
学习必须往深处挖,挖的越深,基础越扎实!
阶段1、深入多线程
阶段2、深入多线程设计模式
阶段3、深入juc源码解析
码哥源码部分
码哥讲源码-原理源码篇【2024年最新大厂关于线程池使用的场景题】
码哥讲源码-原理源码篇【揭秘join方法的唤醒本质上决定于jvm的底层析构函数】
码哥源码-原理源码篇【Doug Lea为什么要将成员变量赋值给局部变量后再操作?】
码哥讲源码【谁再说Spring不支持多线程事务,你给我抽他!】
打脸系列【020-3小时讲解MESI协议和volatile之间的关系,那些将x86下的验证结果当作最终结果的水货们请闭嘴】
延迟队列存储的对象是对应的延迟消息,所谓的延迟消息是指当消息被发送以后,并不想让消费者立刻拿到消息,而是等待特定时间后,消费者才能拿到这个消息进行消费。
延迟消息使用的场景有很多,比如:
- 在订单系统中,一个用户下单之后通常有30分钟的时间进行支付,如果30分钟之内没有支付成功,那么这个订单将进行异常处理,这时候就可以使用延迟队列来处理这些订单了。
- 用户希望通过手机远程遥控家里的智能设备在指定的时间进行工作,这时候就可以将用户指令发送到延迟队列,当指令设定的时间到了再将指令推送到只能设备。
在AMQP协议中,或RabbitMQ本身没有直接支持延迟队列的功能,但是可以通过TTL和DLX模拟出延迟队列的功能;也可以通过rabbitmq_delayed_message_exchange插件来实现。
DLX和TTL模拟延迟队列
-
消息变成死信一般由以下几种情况
- 消息被拒绝(Basic.Reject/Basic.Nack),并且设置requeue参数为false;
- 消息过期
- 队列达到最大长度
-
DLX
DLX是一个正常的交换器,和一般的交换器没有区别,它能在任何的队列上被指定,实际上就是设置某个队列的属性。当这个队列中存在死信时,RabbitMQ就会自动地将这个消息重新发布到设置的DLX上去,进而被路由到另一个队列,即死信队列。可以监听这个队列中的消息进行相应的处理,这个特性与将消息的TTL设置为0配合使用可以弥补immediate参数的功能。
- 声明队列、交换器、绑定路由并在容器启动时自动创建,通过在队列的参数上设置x-dead-letter-exchange参数添加死信交换器,设置x-dead-letter-routing-key参数添加死信路由
package com.yaomy.control.rabbitmq.amqp.ttl.config;
import com.google.common.collect.Maps;
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Map;
/**
* @Description: RabbitMQ生产者交换器、绑定、队列声明
* @Version: 1.0
*/
@SuppressWarnings("all")
@Configuration
public class RabbitConfig {
public static final String TTL_TOPIC_EXCHANGE = "ttl.topic.exchange";
public static final String TTL_TOPIC_QUEUE = "ttl_topic_queue";
public static final String TTL__TOPIC_ROUTING_KEY = "*.topic.*";
public static final String TTL_DELAY_EXCHANGE = "ttl.dlx.exchange";
public static final String TTL_DELAY_ROUTING_KEY = "ttl.dlrk.routingkey";
public static final String TTL_DELAY_QUEUE = "ttl_dlk_queue";
/**
* 声明队列
*/
@Bean
public Queue topicQueue(){
Map<String, Object> args = Maps.newHashMap();
/**
* 设置消息发送到队列之后多久被丢弃,单位:毫秒
*/
args.put("x-message-ttl", 10000);
/**
* 消息变成死信一般由以下几种情况引起:
* 1.消息被拒绝,并且设置requeue参数为false
* 2.消息过期
* 3.队列达到最大长度
* x-dead-letter-exchange参数是指消息编程死信之后重新发送的DLX
*/
args.put("x-dead-letter-exchange", TTL_DELAY_EXCHANGE);
/**
* 为DLX指定路由键DLK
*/
args.put("x-dead-letter-routing-key", TTL_DELAY_ROUTING_KEY);
/**
* 定义优先级队列,消息最大优先级为15,优先级范围为0-15,数字越大优先级越高
*/
args.put("x-max-priority", 15);
/**
* 设置持久化队列
*/
return QueueBuilder.durable(TTL_TOPIC_QUEUE).withArguments(args).build();
}
/**
* 声明Topic类型交换器
*/
@Bean
public TopicExchange topicExchange(){
TopicExchange exchange = new TopicExchange(TTL_TOPIC_EXCHANGE);
return exchange;
}
/**
* Topic交换器和队列通过bindingKey绑定
* @return
*/
@Bean
public Binding bindingTopicExchangeQueue(){
return BindingBuilder.bind(topicQueue()).to(topicExchange()).with(TTL__TOPIC_ROUTING_KEY);
}
//============================延迟队列及交换器定义=================================
/**
* 定义延迟队列
*/
@Bean
publi