rabbitmq延时队列

使用场景:定时发送邮件,定时过期等

  • 所需依赖
<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.2.2.RELEASE</version>
</parent>
<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
  </dependency>
  <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
  </dependency>
  <dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.68</version>
  </dependency>
</dependencies>
  • yml配置
mess:
  mq:
    url: 127.0.0.1:5672
    name: guest
    pass: guest
  • rabbitmq配置类
package org.example.rabbitmq2.config;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import java.util.HashMap;
import java.util.Map;

/**
 * rabbitmq配置类
 */
@Configuration
public class RabbitmqConfig {
    @Value("${mess.mq.url}")
    String mess_mq_url;
    @Value("${mess.mq.name}")
    String mess_mq_name;
    @Value("${mess.mq.pass}")
    String mess_mq_pass;
    //exchange name
    public static final String EXCHANGE_MESSAGE = "exchange.message";
    //最终处理业务queue
    public static final String QUEUE_MESSAGE_SOLVE = "message.solve.queue";
    //转发(延时)队列
    public static final String QUEUE_MESSAGE_DELAY_PACK = "message.delay.pack.queue";
    //死信拥堵队列
    public static final String QUEUE_MESSAGE_DELAY_DEAD = "message.delay.dead.queue";

    @Bean
    public ConnectionFactory connectionFactory() {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory();
        connectionFactory.setAddresses(mess_mq_url);
        connectionFactory.setUsername(mess_mq_name);
        connectionFactory.setPassword(mess_mq_pass);
        connectionFactory.setVirtualHost("/");
        //必须要设置 
        connectionFactory.setPublisherConfirms(true);
        connectionFactory.setChannelCacheSize(20);
        return connectionFactory;
    }
    /**
    * @Description: 必须是prototype类型  不能为单例模式  
    * @Param: []
    * @Author: wb
    * @Date: 2022/08/19 10:22 AM
    */
    @Bean
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public RabbitTemplate rabbitTemplate() {
        RabbitTemplate template = new RabbitTemplate(connectionFactory());
        template.setConfirmCallback(new ConfirmCallBackListener());
        template.setReturnCallback(new ReturnCallBackListener());
        template.setMandatory(true);
        return template;
    }
    //信道配置
    @Bean
    public DirectExchange messageExchange() {
        return new DirectExchange(RabbitmqConfig.EXCHANGE_MESSAGE, true, false);
    }
    /*********************    业务队列定义与绑定   *****************/
    @Bean
    public Queue messageSolveQueue() {
        Queue queue = new Queue(RabbitmqConfig.QUEUE_MESSAGE_SOLVE,true);
        return queue;
    }
    @Bean
    public Binding messageSolveBinding() {
        //队列绑定到exchange上,再绑定好路由键
        return BindingBuilder.bind(messageSolveQueue()).to(messageExchange()).with(RabbitmqConfig.QUEUE_MESSAGE_SOLVE);
    }
    /*********************   业务队列定义与绑定  *****************/
    //下面是延迟(包装)队列的配置
    //转发(延时)队列
    @Bean
    public Queue messageDelayPackQueue() {
        Queue queue = new Queue(RabbitmqConfig.QUEUE_MESSAGE_DELAY_PACK,true,false,false);
        return queue;
    }
    //绑定转发(延时)队列
    @Bean
    public Binding messageDelayPackBinding() {
        return BindingBuilder.bind(messageDelayPackQueue()).to(messageExchange()).with(RabbitmqConfig.QUEUE_MESSAGE_DELAY_PACK);
    }
    //死信队列  -- 消息在死信队列上堆积,消息超时时,会把消息转发到转发队列,转发队列根据消息内容再把转发到指定的队列上
    @Bean
    public Queue messageDelayDeadQueue() {
        Map<String, Object> arguments = new HashMap<>();
        arguments.put("x-dead-letter-exchange", RabbitmqConfig.EXCHANGE_MESSAGE);
        arguments.put("x-dead-letter-routing-key", RabbitmqConfig.QUEUE_MESSAGE_DELAY_PACK);
        //拥堵队列
        Queue queue = new Queue(RabbitmqConfig.QUEUE_MESSAGE_DELAY_DEAD,true,false,false,arguments);
        return queue;
    }
    //绑定死信队列
    @Bean
    public Binding messageDelayDeadBinding() {
        return BindingBuilder.bind(messageDelayDeadQueue()).to(messageExchange()).with(RabbitmqConfig.QUEUE_MESSAGE_DELAY_DEAD);
    }
}
  • confirm回调类
package org.example.rabbitmq2.config;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Component;
/**
  如果消息没有到exchange,则confirm回调,ack=false
  如果消息到达exchange,则confirm回调,ack=true
 */
@Component
public class ConfirmCallBackListener implements RabbitTemplate.ConfirmCallback {
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        System.out.println("confirm--:correlationData:"+correlationData+",ack:"+ack+",cause:"+cause);
    }
}
  • return回调类
package org.example.rabbitmq2.config;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Component;
/**
 exchange到queue成功,则不回调return
 exchange到queue失败,则回调return(需设置mandatory=true,否则不回回调,消息就丢了)
 */
@Component
public class ReturnCallBackListener implements RabbitTemplate.ReturnCallback {
    @Override
    public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
        System.out.println("return--message:" + new String(message.getBody()) + ",replyCode:" + replyCode + ",replyText:" + replyText + ",exchange:" + exchange + ",routingKey:" + routingKey);
    }
}
  • 延时消息实体类
package org.example.rabbitmq2.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import java.io.Serializable;
/**
 * 延迟消息实体类
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class DLXMessage implements Serializable {
    private static final long serialVersionUID = 9956432152000L;
    private String exchange;
    private String queueName;
    private String content;
    private long times;
}
  • 消息发送类
package org.example.rabbitmq2.producer;
import com.alibaba.fastjson.JSON;
import org.example.rabbitmq2.entity.DLXMessage;
import org.example.rabbitmq2.config.RabbitmqConfig;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.UUID;
/**
 * 消息发送
 */
@Component
public class RabbitmqSend {
    private RabbitTemplate rabbitTemplate;
    @Autowired
    public RabbitmqSend(RabbitTemplate rabbitTemplate) {
        this.rabbitTemplate = rabbitTemplate;
    }
    /**
     * 发送延时消息
     * @param content
     * @param times 
     */
    public void sendDelayMsg(String content,final long times) {
        DLXMessage dlxMessage = new DLXMessage(RabbitmqConfig.EXCHANGE_MESSAGE,RabbitmqConfig.QUEUE_MESSAGE_SOLVE,content,times);
        MessagePostProcessor processor = new MessagePostProcessor(){
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                message.getMessageProperties().setExpiration(times + "");
                return message;
            }
        };
        CorrelationData correlationId = new CorrelationData(UUID.randomUUID().toString());
        rabbitTemplate.convertAndSend(RabbitmqConfig.EXCHANGE_MESSAGE,
                RabbitmqConfig.QUEUE_MESSAGE_DELAY_DEAD, JSON.toJSONString(dlxMessage), processor,correlationId);
    }
}
package org.example.rabbitmq2.consumer;
import com.alibaba.fastjson.JSON;
import org.example.rabbitmq2.entity.DLXMessage;
import org.example.rabbitmq2.config.RabbitmqConfig;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.UUID;
/**
 * 转发(延时)消费者
 */
@Component
public class MessageDelayPackConsumer {
    @Autowired
    private RabbitTemplate rabbitTemplate;
    //监听转发(延时)队列,有消息时,把消息转发到目标队列
    @RabbitListener(queues = RabbitmqConfig.QUEUE_MESSAGE_DELAY_PACK)
    public void delayPackMessage(String content) {
        try {
            //此时,才把消息发送到指定队列,而实现延迟功能
            DLXMessage message = JSON.parseObject(content, DLXMessage.class);
            System.err.println("将消息转发给其他队列------------"+message.getQueueName());
            CorrelationData correlationId = new CorrelationData(UUID.randomUUID().toString());
            rabbitTemplate.convertAndSend(RabbitmqConfig.EXCHANGE_MESSAGE,message.getQueueName(), message.getContent(),correlationId);
            System.err.println("转发到-------------"+message.getQueueName());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
  • 业务处理消费者
package org.example.rabbitmq2.consumer;
import org.example.rabbitmq2.config.RabbitmqConfig;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
/**
 * 业务处理消费者
 */
@Component
public class MessageSolveConsumer {
    @RabbitListener(queues = RabbitmqConfig.QUEUE_MESSAGE_SOLVE)
    public void sendMailDelayTradeMessage(String content) {
        try {
            System.out.println("接收到的消息------------------------------"+content);
        }catch (Exception e){
           e.printStackTrace();
        }
    }
}
  • 测试类
package org.example.controller;
import org.example.rabbitmq2.producer.RabbitmqSend;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
/**
 * Controller测试类
 */
@RestController
@RequestMapping("/test")
public class MyTestController {
    @Autowired
    private RabbitmqSend rabbitmqSend;
    @RequestMapping("/sendMsg")
    public void sendMessage(@RequestParam("message") String message,@RequestParam("times")Long times){
        rabbitmqSend.sendDelayMsg( message, times);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值