RabbitMQ消息队列(七):过期时间TTL、死信队列、延迟队列、消息确认

RabbitMQ消息队列(七):过期时间TTL、死信队列、延迟队列、消息确认

队列设置及参数:

参数名类型作用
x-message-tti(Time-To-Live)int,毫秒对消息设置预期的时间,过期将被丢弃
x-max-lengthint限制队列最大长度,个数,新增后删除最早的
x-expiresint,毫秒队列没有访问超时时,自动删除时间
x-max-length-bytesint限制队列最大容量
x-dead-letter-exchangeString指定死信交换机
x-dead-letter-routing-keyString死信路由,指定routingKey
x-max-priorityint队列优先级
x-queue-mode默认"lazy"对列模式,默认lazy(将数据放入磁盘,消费时放入内存)
x-queue-master-locatorQueueBuilder.MasterLocator主队列选择策略,min-masters:选择承载最小绑定主机数量的节点,client-local:选择客户机声明队列连接到的节点,min-masters:随机选择一个节点
    @Bean
    public Queue paramQueue() {
        Map<String, Object> map = new HashMap<>();
        // 队列设置消息过期时间 60 秒
        map.put("x-message-ttl", 60 * 1000);
        // 队列设置最大长度 10
        map.put("x-max-length", 10);
        // ....
        return new Queue("paramQueue", true, false, false, map);
    }

1. 过期时间TTL

过期时间 TTL 表示可以对消息设置预期的时间,在这个时间内都可以被消费者接收获取;过了之后消息将自动被删除。RabbitMQ 可以对消息和队列设置 TTL。
目前有两种方法可以设置(基于SpringBoot)。
第一种方法是通过队列属性设置,队列中所有消息都有相同的过期时间。

  @Bean("work_queue")
  public Queue itemQueue() {
   return QueueBuilder.durable("work_queue").ttl(1000).build();
  }

设置范围为0 <= n <=2^32-1;

第二种方法是对消息进行单独设置,每条消息 TTL 可以不同。

  MessageProperties messageProperties = new MessageProperties();
  //设置消息的过期时间,60 秒
  messageProperties.setExpiration("60000");
  Message msg = new Message("TTL message".getBytes(), messageProperties);
  //路由键
  rabbitTemplate.convertAndSend("topic.exchange", "routeKey", msg);

expiration 字段以微秒为单位表示 TTL 值,且字段必须为字符串类型,broker 将只会接受以字符串形式表达的数字。当同时指定了 queue 和 message 的 TTL 值,则两者中较小的那个才会起作用。

2. 死信队列

DLX,全称为 Dead-Letter-Exchange , 可以称之为死信交换机,也有人称之为死信邮箱。当消息在一个队列中变成死信(dead message)之后,它能被重新发送到另一个交换机中,这个交换机就是 DLX ,绑定 DLX 的队列就称之为死信队列。

消息变成死信,可能是由于以下的原因:

  • 消息被拒绝

  • 消息过期

  • 队列达到最大长度

DLX 也是一个正常的交换机,和一般的交换机没有区别,它能在任何的队列上被指定,实际上就是设置某一个队列的属性。当这个队列中存在死信时,Rabbitmq 就会自动地将这个消息重新发布到设置的 DLX 上去,进而被路由到另一个队列,即死信队列。

	//死信交换机
	@Bean
    DirectExchange deadExchange() {
        return new DirectExchange("deadExchange", true, false);
    }

然后绑定路由和队列;

3. 延迟队列

当有需要在指定的某个时间之后执行的任务都可以通过延迟队列处理;

延迟队列存储的对象是对应的延迟消息;所谓“延迟消息” 是指当消息被发送以后,并不想让消费者立刻拿到消息,而是等待特定时间后,消费者才能拿到这个消息进行消费。

在 RabbitMQ 中延迟队列可以通过 过期时间 + 死信队列 来实现;

即在队列中指定延迟时间,当消息超过TTL转到死信队列时,死信队列再按照延迟处理消息。

4.消息确认

image-20220812163827613

  • 消息发动到交换机时的回调
@Component
@Slf4j
public class ConfirmCallback implements RabbitTemplate.ConfirmCallback {

  @Resource
  private RabbitTemplate rabbitTemplate;

  /**
   * 消息发动到交换机时的回调函数
   *
   * @param correlationData correlationData
   * @param sendResult      如果消息发送成功则为true, 反之为false
   * @param message         消息体
   */
  @Override
  public void confirm(CorrelationData correlationData, boolean sendResult, String message) {
    if (!sendResult) {
      log.info("消息发送成功");
    } else {
      log.info("消息发送失败,进行容错处理");
    }
    log.info("消息发动到交换机时的回调函数, ack:" + sendResult + "  消息体:" + message);
  }
  
}
  • 消息从交换机发送到队列时的回调
@Component
@Slf4j
public class ReturnsCallback implements RabbitTemplate.ReturnsCallback{

  /**
   * 消息从交换机发送到队列时的回调函数
   * 如果发送成功则不回调该函数, 反之则回调
   *
   * @param returnedMessage returnedMessage
   */
  @Override
  public void returnedMessage(ReturnedMessage returnedMessage) {
    log.info("消息从交换机发送到队列时的回调函数, 调用失败!!!");
  }

}
  • 消费端手工确认demo
  @RabbitListener(queues="simple_queue")
  public void process(String msg, Channel channel, Message message) throws IOException {
    log.info("ReceiveMessage:"+msg);
    try {
      //消息被消费了 可以在队列删掉 否则后续还会再发
      channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
      log.info("receiver success");
    } catch (IOException e) {
      e.printStackTrace();
      //处理规则
      //1.丢弃这条消息
      //channel.basicNack(message.getMessageProperties().getDeliveryTag(), false,false);
      //2.ack返回false,并重新回到队列
      //channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
      log.info("receiver fail");
    }
  }
;
      //2.ack返回false,并重新回到队列
      //channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
      log.info("receiver fail");
    }
  }
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值