在这里新增了一个队列QC,绑定关系如下,该队列不设置TTL时间
配置类文件:
@Bean("queueC") public Queue queueC() { HashMap<String, Object> args = new HashMap<String, Object>(); args.put("x-dead-letter-exchange",Y_DEAD_LETTER_EXCHANGE); args.put("x-dead-letter-routing-key","YD"); //在这里没有声明TTL属性 return QueueBuilder.durable(QUEUE_C).withArguments(args).build(); } @Bean public Binding queueBindingX(@Qualifier("queueC") Queue queueC,@Qualifier("xExchange") DirectExchange exchange) { return BindingBuilder.bind(queueC).to(exchange).with("XC"); }
生产者:
@Slf4j @RequestMapping("ttl") @RestController public class Produce01 { @Autowired private RabbitTemplate rabbitTemplate; // @GetMapping("sendMsg/{message}") // public void sendMsg(@PathVariable String message) // { // // log.info("当前时间:{},发送一条消息给俩个TTL队列:{}", new Date(),message); // rabbitTemplate.convertAndSend("X","XA","消息来于10s"+message); // rabbitTemplate.convertAndSend("X","XB","消息来于40s"+message); // } @GetMapping("sendExpirationMsg/{message}/{ttlTime}") public void senMsg(@PathVariable String message,@PathVariable String ttlTime) { log.info("当前时间:{},发送一条时长{}毫秒TTL信息给队列C:{}", new Date(),ttlTime, message); rabbitTemplate.convertAndSend("X","XC",message, correlationData ->{ correlationData.getMessageProperties().setExpiration(ttlTime); return correlationData; }); } }
消费者:
@Slf4j @Component public class Consumer { @RabbitListener(queues = "QD") public void receiveD(Message message, Channel channel) { String s = new String(message.getBody()); log.info("当前时间{},死信队列D接收到消息---->{}",new Date(),s); } }
看起来似乎没什么问题,但是在最开始的时候,就介绍过如果使用在消息属性上设置TTL的方式,消息可能并不会按时“死亡“,因为RabbitMQ只会检查第一个消息是否过期,如果过期则丢到死信队列,
如果第一个消息的延时时长很长,而第二个消息的延时时长很短,第二个消息并不会优先得到执行。