Rabbitmq的延时队列的使用

配置:

spring:
  rabbitmq:
    addresses: 192.168.108.128:5672
    connection-timeout: 15000
    username: guest
    password: guest
    publisher-confirms: true
    publisher-returns: true

依赖:

  <!--rabbitmq -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>

配置类:

package com.jds.rabbitmq;

import com.jds.common.constant.QueueEnum;
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

@Configuration
public class MQConfig {
    
    public static final String RBA_QUEUE = "rba.queue";
/*    public static final String QUEUE = "queue";
    public static final String TOPIC_QUEUE1 = "topic.queue1";
    public static final String TOPIC_QUEUE2 = "topic.queue2";
    public static final String HEADER_QUEUE = "header.queue";
    public static final String TOPIC_EXCHANGE = "topicExchage";
    public static final String FANOUT_EXCHANGE = "fanoutxchage";
    public static final String HEADERS_EXCHANGE = "headersExchage";
    
    *//**
     * Direct模式 交换机Exchange
     * *//*
    @Bean
    public Queue queue() {
        return new Queue(QUEUE, true);
    }
    
    *//**
     * Topic模式 交换机Exchange
     * *//*
    @Bean
    public Queue topicQueue1() {
        return new Queue(TOPIC_QUEUE1, true);
    }
    @Bean
    public Queue topicQueue2() {
        return new Queue(TOPIC_QUEUE2, true);
    }
    @Bean
    public TopicExchange topicExchage(){
        return new TopicExchange(TOPIC_EXCHANGE);
    }
    @Bean
    public Binding topicBinding1() {
        return BindingBuilder.bind(topicQueue1()).to(topicExchage()).with("topic.key1");
    }
    @Bean
    public Binding topicBinding2() {
        return BindingBuilder.bind(topicQueue2()).to(topicExchage()).with("topic.#");
    }
    *//**
     * Fanout模式 交换机Exchange
     * *//*
    @Bean
    public FanoutExchange fanoutExchage(){
        return new FanoutExchange(FANOUT_EXCHANGE);
    }
    @Bean
    public Binding FanoutBinding1() {
        return BindingBuilder.bind(topicQueue1()).to(fanoutExchage());
    }
    @Bean
    public Binding FanoutBinding2() {
        return BindingBuilder.bind(topicQueue2()).to(fanoutExchage());
    }
    *//**
     * Header模式 交换机Exchange
     * *//*
    @Bean
    public HeadersExchange headersExchage(){
        return new HeadersExchange(HEADERS_EXCHANGE);
    }
    @Bean
    public Queue headerQueue1() {
        return new Queue(HEADER_QUEUE, true);
    }
    @Bean
    public Binding headerBinding() {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("header1", "value1");
        map.put("header2", "value2");
        return BindingBuilder.bind(headerQueue1()).to(headersExchage()).whereAll(map).match();
    }*/

    /**
     * 订单消息实际消费队列所绑定的交换机
     */
    @Bean
    DirectExchange orderDirect() {
        return (DirectExchange) ExchangeBuilder
                .directExchange(QueueEnum.QUEUE_ORDER_CANCEL.getExchange())
                .durable(true)
                .build();
    }

    /**
     * 订单延迟队列队列所绑定的交换机
     */
    @Bean
    DirectExchange orderTtlDirect() {
        return (DirectExchange) ExchangeBuilder
                .directExchange(QueueEnum.QUEUE_TTL_ORDER_CANCEL.getExchange())
                .durable(true)
                .build();
    }

    /**
     * 订单实际消费队列
     */
    @Bean
    public Queue orderQueue() {
        return new Queue(QueueEnum.QUEUE_ORDER_CANCEL.getName());
    }

    /**
     * 订单延迟队列(死信队列)
     */
    @Bean
    public Queue orderTtlQueue() {
        return QueueBuilder
                .durable(QueueEnum.QUEUE_TTL_ORDER_CANCEL.getName())
                .withArgument("x-dead-letter-exchange", QueueEnum.QUEUE_ORDER_CANCEL.getExchange())//到期后转发的交换机
                .withArgument("x-dead-letter-routing-key", QueueEnum.QUEUE_ORDER_CANCEL.getRouteKey())//到期后转发的路由键
                .build();
    }

    /**
     * 将订单队列绑定到交换机
     */
    @Bean
    Binding orderBinding(DirectExchange orderDirect,Queue orderQueue){
        return BindingBuilder
                .bind(orderQueue)
                .to(orderDirect)
                .with(QueueEnum.QUEUE_ORDER_CANCEL.getRouteKey());
    }

    /**
     * 将订单延迟队列绑定到交换机
     */
    @Bean
    Binding orderTtlBinding(DirectExchange orderTtlDirect,Queue orderTtlQueue){
        return BindingBuilder
                .bind(orderTtlQueue)
                .to(orderTtlDirect)
                .with(QueueEnum.QUEUE_TTL_ORDER_CANCEL.getRouteKey());
    }

    
    
}

发送者:

package com.jds.rabbitmq;

/**
 * @program: red-bag-activity->CancelOrderSender
 * @description:
 * @author: cxy
 * @create: 2019-12-20 17:57
 **/

import com.jds.common.constant.QueueEnum;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * 取消订单消息的发出者
 *
 */
@Component
public class CancelOrderSender {
    private static Logger LOGGER =LoggerFactory.getLogger(CancelOrderSender.class);
    @Autowired
    private AmqpTemplate amqpTemplate;

    public void sendMessage(Long orderId,final long delayTimes){
        //给延迟队列发送消息
        amqpTemplate.convertAndSend(QueueEnum.QUEUE_TTL_ORDER_CANCEL.getExchange(), QueueEnum.QUEUE_TTL_ORDER_CANCEL.getRouteKey(), orderId, new MessagePostProcessor() {
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                //给消息设置延迟毫秒值
                message.getMessageProperties().setExpiration(String.valueOf(delayTimes));
                return message;
            }
        });
        LOGGER.info("send delay message orderId:{}",orderId);
    }
}

接受者:

package com.jds.rabbitmq;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * 取消订单消息的处理
 */
@Component
@RabbitListener(queues = "mall.order.cancel")
public class CancelOrderReceiver {
    private static Logger LOGGER =LoggerFactory.getLogger(CancelOrderReceiver.class);

    @RabbitHandler
    public void handle(Long orderId){
        System.err.println(System.currentTimeMillis());
        LOGGER.info("receive delay message orderId:{}",orderId);
        System.err.println(System.currentTimeMillis());
        System.err.println(orderId);
        System.out.println("大傻逼222222");
    }
}

配置调用类:

package com.jds.controller;

import com.jds.rabbitmq.CancelOrderSender;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

/**
 * @program: red-bag-activity->DelayQController
 * @description:
 * @author: cxy
 * @create: 2019-12-20 18:00
 **/
@RestController
public class DelayQController {
    @Autowired
    CancelOrderSender cancelOrderSender;
    @RequestMapping(value = "/id", method = RequestMethod.GET)
    @ResponseBody
    public void detail() {
        long delayTimes = 3 * 1000;
        //发送延迟消息
        cancelOrderSender.sendMessage(12333333L, delayTimes);
        System.out.println(12333333L);
        System.err.println(delayTimes);
        System.out.println(System.currentTimeMillis());

        System.out.println("  大傻逼");



        }
}

测试结果:

2019-12-20 21:48:44.932 |-INFO  [http-nio-8082-exec-1] com.jds.rabbitmq.CancelOrderSender [40] -| send delay message orderId:12333333
12333333
1576849724932
  大傻逼
3000
1576849727975
2019-12-20 21:48:47.975 |-INFO  [org.springframework.amqp.rabbit.RabbitListenerEndpointContainer#0-1] com.jds.rabbitmq.CancelOrderReceiver [21] -| receive delay message orderId:12333333
1576849727975
大傻逼222222
12333333

调用:

http://localhost:8082/id,可以看到时间会延迟三秒。

实现主要地方:

new MessagePostProcessor() {
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                //给消息设置延迟毫秒值
                message.getMessageProperties().setExpiration(String.valueOf(delayTimes));
                return message;
            }

给参数设置延迟时间

### RabbitMQ中配置延时队列以确保高优先级消息或最新消息被优先处理 为了确保在RabbitMQ中配置的延时队列能够使高优先级的消息或是最新的消息得到优先处理,需要综合考虑多个方面。一方面,在创建队列的时候要指定`x-max-priority`参数来定义最大优先级数值,从而支持基于优先级的消息调度机制[^1];另一方面,对于延时功能,则需借助于特定类型的交换机——即带有`x-delayed-message`特性的自定义插件实现方式。 具体来说: - **启用必要的插件**:首先应当确认已安装并启用了`rabbitmq_delayed_message_exchange`插件,这一步骤是构建具备延时能力的基础环境所必需的操作[^5]。 - **声明带优先级的支持队列**:当声明用于承载待发送数据包的目标队列时,应指明其具有多等级别的特性,并设定合理的最高级别界限值(例如8)。这样做的目的是为了让后续进入该通道内的每一条记录都能够携带自身的紧急程度标识符,进而影响到它们之间相对顺序安排的可能性。 ```yaml spring.rabbitmq.listener.direct.concurrency=3 spring.rabbitmq.template.exchange=my.priority.delayed.exchange spring.rabbitmq.queue.name=priority.delayed.queue spring.rabbitmq.queue.arguments.x-max-priority=8 ``` - **配置延迟交换器**:接着就是针对上述提到过的特殊性质交换实例进行初始化工作了。这里会涉及到一些额外选项的选择与调整,比如将类型设为`'x-delayed-message'`以及关联起之前建立好的持久化存储空间实体等操作。 ```java @Bean public CustomExchange delayedExchange() { Map<String, Object> args = new HashMap<>(); args.put("x-delayed-type", "direct"); return new CustomExchange("my.priority.delayed.exchange", "x-delayed-message", true, false, args); } ``` - **发布含有时间戳和优先权级别的消息体**:最后一点也是最为重要的环节在于实际向网络上传输的信息内容本身的设计上。除了常规的有效载荷之外,还需附加两个关键属性字段:“expiration”用来表示预期等待周期长度,“priority”则决定了当前项在整个序列里边的位置权重关系[^2]。 ```java MessageProperties messageProperties = new MessageProperties(); messageProperties.setExpiration(String.valueOf(5000)); // 设置过期时间为5秒 messageProperties.setPriority(8); // 设定较高优先级 amqpTemplate.convertAndSend(exchangeName, routingKey, content, messageProperties); ``` 通过以上措施可以在很大程度上满足关于如何让某些重要指令尽快被执行的需求目标,同时也兼顾到了不同场景下灵活应对变化的能力需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值