RabbitMQ系列(2)-TTL实现延迟消费

前言

延迟消费在实际开发中有很多的应用场景,例如:一条消息,需要在30分钟后消费,这个时候就可以使用消息的TTL属性实现延迟消费。具体的实现思路:
生产者发送消息 -----> 交换机 ------> 路由到消息队列(设置消息的TTL属性,表示消息失效后路由到死信交换机) ----> 死信交换机 ----> 路由到死信队列,从死信队列中消费

具体代码

生产者和消费者代码(可以写在同一类中,也可以分开)

/**
 * 消息生产者.
 * 消息通过正常交换机路由到正常队列,在正常队列中设置消息TTL最大存活时间,超过时间后,消息进入死信交 
 * 换机,死信交换机将消息路由到死信队列,死信队列也就是实际消费队列,
 * 死消费者从实际消费队列中消费消息.
 */
@Component
@Slf4j
public class CustomerProducer {

  @Autowired
  private RabbitTemplate rabbitTemplate;

  /**
   * 正常交换机.
   */
  public static final String NORMAL_EXCHANGE = "shop.pay.normal.exchange";
  /**
   * 死信交换机.
   */
  public static final String DL_EXCHANGE = "shop.pay.dl.exchange";
  /**
   * 正常队列.
   */
  public static final String NORMAL_QUEUE = "shop.pay.normal.queue";
  /**
   * 死信队列.
   */
  public static final String DL_QUEUE = "shop.pay.dl.queue";

  /**
   * 初始化交换机和队列.
   */
  @Bean
  public DirectExchange normalExchange() {
    return new DirectExchange(NORMAL_EXCHANGE);
  }
  @Bean
  public FanoutExchange dlExchange() {
    return new FanoutExchange(DL_EXCHANGE);
  }
  @Bean
  public Queue normalQueue() {
    Map<String,Object> args = new HashMap<>();
    args.put("x-dead-letter-exchange", DL_EXCHANGE);
    args.put("x-dead-letter-routing-key", DL_QUEUE);
    // 参数解释:durable:是否持久化,exclusive:仅创建者可以使用的私有队列,断开后自动删除
    // autoDelete:当所有消费客户端断开连接后,是否自动删除队列
    return new Queue(NORMAL_QUEUE, true, false, false, args);
  }
  @Bean
  public Queue dlQueue() {
    return new Queue(DL_QUEUE,true,false,false);
  }

  /**
   * 队列和交换机绑定.
   */
  @Bean
  public Binding normalBinding() {
    return BindingBuilder.bind(dlQueue()).to(dlExchange());
  }
  @Bean
  public Binding dlBinding() {
    return BindingBuilder.bind(normalQueue()).to(normalExchange()).with("KEY1");
  }

  /**
   * 发送消息.
   *
   */
  public void sendMessage(String message) {
    log.info("sendMessage,发送MQ延时消息,message", message);
    // 发送消息
    try {
      // 设置队列的TTL为3000毫秒,如果超过3000毫秒内没有消费者从队列(通过路由键KEY1
      // 路由到与NORMAL_EXCHANGE绑定的NORMAL_QUEUE队列中)中消费该消息,消息就会被转
      // 发到队列绑定的死信交换机中,可以监听死信队列,从私信队列中获取到超时的消息
      MessagePostProcessor processor = message1 -> {
        message1.getMessageProperties().setExpiration("3000");
        return message1;
      };
      rabbitTemplate.convertAndSend(NORMAL_EXCHANGE, "KEY1",  (Object) message, processor);
    } catch (Exception e) {
      log.error("消息发送失败", e);
    }
  }
  
  /**
   * 消费者.
   * 监听死信队列.
   *
   * @param msg 消息内容.
   */
  @RabbitHandler
  @RabbitListener(queues = DL_QUEUE)
  public void process(String msg) {
    log.info("process,消费端入参,msg={}", msg);
  }
}

发送消息代码

@RestController
public class Main {

    @Autowired
    private CustomerProducer producer;
    /**
     * 发送消息.
     */
    @GetMapping("produce")
    public void sendMessage() {
        producer.sendMessage("hello world");
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值