rabbitmq之基于插件的延时队列(六)

前言

基于死信的延时队列文章链接
在上一篇rabbitmq基于死信的延时队列中提到了,通过rabbitmq的消息过期机制实现的延时队列,RabbitMQ 只会检查第一个消息是否过期,如果过期则丢到死信队列,如果第一个消息的延时时长很长,而第二个消息的延时时长很短,第二个消息并不会优先得到执行。

rabbitmq之基于插件的延时队列

针对这一问题我们就可以通过rabbitmq_delayed_message_exchange插件实现rabbitmq的延时队列。从而达到并行计算消息过期时间的问题。

安装延时队列插件

  1. 通过官网下载 https://www.rabbitmq.com/community-plugins.html
    rabbitmq_delayed_message_exchange 插件,然后解压放置到 RabbitMQ 的插件目录。
  2. 接下来,进入RabbitMQ的安装目录下的sbin目录,执行下面命令让该插件生效,然后重启RabbitMQ。
rabbitmq-plugins enable rabbitmq_delayed_message_exchange

在这里插入图片描述
安装成功后,rabbitmq监控页面的交换机会新增一个
x-delayed-message的类型。
在这里插入图片描述

流程图

基于死信的延时队列流程图
在这里插入图片描述
基于rabbitmq_delayed_message_exchange插件的流程图
在这里插入图片描述

代码演示

代码模拟下图
在这里插入图片描述
配置文件中添加rabbitmq的配置

spring.rabbitmq.host=192.168.136.128
spring.rabbitmq.port=5672
spring.rabbitmq.username=admin
spring.rabbitmq.password=admin

引入rabbitmq的依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

添加配类

        @Configuration
        public class DelayedQueueConfig {
        	//延迟队列名称
            public static final String DELAYED_QUEUE_NAME = "delayed.queue";
            //延迟交换机名称
            public static final String DELAYED_EXCHANGE_NAME = "delayed.exchange";
            //延迟队列routingkey
            public static final String DELAYED_ROUTING_KEY = "delayed.routingkey";
			
			//声明延迟队列
            @Bean("delayedQueue")
            public Queue delayedQueue() {
                return new Queue(DELAYED_QUEUE_NAME);
            }
      
            //自定义交换机 我们在这里定义的是一个延迟交换机
            @Bean("delayedExchange")
            public CustomExchange delayedExchange()
            { 
            	Map<String, Object> args = new HashMap<>();
				//自定义延迟交换机的类型,fanout丶direct丶Topic都可以根据业务来
                args.put("x-delayed-type", "direct");
                return new CustomExchange(DELAYED_EXCHANGE_NAME, "x-delayed-message", true, false,args);
            }
			//将延迟队列与延迟交换机绑定
            @Bean
            public Binding bindingDelayedQueue(@Qualifier("delayedQueue") Queue queue,
                                               @Qualifier("delayedExchange") CustomExchange delayedExchange) {
                return BindingBuilder.bind(queue).to(delayedExchange).with(DELAYED_ROUTING_KEY).noargs();
            }
        }

//因为是基于插件的延时队列,所以声明交换机的时候,类型需要是定制的CustomExchange

添加生产者

@Slf4j
@RequestMapping
@RestController
public class DelayedQueueProducer{
	@Autowired
	private RabbitTemplate rabbitTemplate;
	
	@GetMapping("sendDelayMsg/{message}/{delayTime}")
	public void sendMsg((@PathVariable String message,@PathVariable Integer delayTime){
		log.info("当前时间:{},发送一条时长{}毫秒消息给延迟队列delayed.queue:{},new Date(),toString(),delayTime,message");
		
		rabbitTemplate.convertAndSend(DelayedQueueConfig.DELAYED_EXCHANGE_NAME, DelayedQueueConfig.DELAYED_ROUTING_KEY, message,msg->{
			msg.getMessageProperties().setDelay(delayTime);
			return msg;
		});
	}
}

添加消费者

@Slf4j
@Component
public class DelayedQueueConsumer{
	//指定消费的队列
	@RabbitListener(queues = DelayedQueueConfig.DELAYED_QUEUE_NAME)
	public void receiveDelayedQueue(Message message)
	{
		String msg = new String(message.getBody());
		log.info("当前时间:{},收到延迟队列的消息:{}", new Date().toString(), msg);
	}
}

发送请求,模拟发送一条延时20s的消息和延时2s的消息
首先发送 sendDelayMsg/come on baby1/20000
接着发送 sendDelayMsg/come on baby2/2000
观察结果
在这里插入图片描述

我们发现虽然发送的第一条消息是baby1,但是这次baby2先被消费掉了,所以证明通过插件实现的延时队列,可以并行计算过期时间。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值