对消息或者队列设置过期时间,则时间到了相应的消息或者队列里的全部消息都被删除并放到死信队列里,消费者无法消费。如果对消息和该消息所在队列都设置了过期时间,则以过期时间短的为准(以先过期的为准)
声明队列时需要设置x-message-ttl属性,并设置过期时间,推送到该队列中的所有消息,在时间到后都会被删除并放到死信队列中
/**
* 声明过期队列
* @return
*/
@Bean
public Queue test2Queue() {
Map<String, Object> map = new HashMap<>();
map.put("x-message-ttl", 5000); // 队列中的每一个消息未被消费则5秒后过期,被自动删除并移到死信队列
return new Queue("test2_Queue",true,false,false,map);
}
生产者代码:
@GetMapping("/sendMessage")
public void sendMessage() {
MessageProperties messageProperties = new MessageProperties();
//设置过期时间
messageProperties.setExpiration("10000");
//这个参数是用来做消息的唯一标识
//发布消息时使用,存储在消息的headers中
CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
Message message = new Message("lalalalla".getBytes(StandardCharsets.UTF_8), messageProperties);
rabbitTemplate.convertAndSend("direct_Exchange", "test1_Queue", message, correlationData);
}
消费者代码:
package com.example.demo.mq;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
@Component
public class Test1QueueReceiver {
@RabbitListener(queues = "test1_Queue")
public void process(String mes, Channel channel, Message message) {
System.err.println(mes);
//消息的所有相关信息都可以在message中找到
System.err.println(message.toString());
}
}
注意:
RabbitMQ只会淘汰队列头部的过期消息。如果单独给一条消息设置ttl,先入队列的消息过期时间如果设置比较长,后入队列的设置时间比较短,那么消息就不会及时的被淘汰,会导致消息的堆积问题。
设置优先级的目的是可以让队列中的消息按照设置好的优先级由大到小排序,然后优先级高的先消费
/**
* 声明优先级队列
* @return
*/
@Bean
public Queue test4Queue() {
Map<String, Object> map = new HashMap<>();
//设置优先级,范围0-255,此处设为10,则本队列允许优先级的范围为0-10。优先级设置的越高,对服务器的压力越大
map.put("x-max-priority", 10);
return new Queue("test4_Queue",true,false,false,map);
}
如果队列有优先级会有Pri标识
@GetMapping("/sendMessage")
public void sendMessage() {
for (Integer i = 1; i < 11; i++) {
MessageProperties messageProperties = new MessageProperties();
//设置优先级
messageProperties.setPriority(i);
//这个参数是用来做消息的唯一标识
//发布消息时使用,存储在消息的headers中
CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
Message message = new Message(i.toString().getBytes(StandardCharsets.UTF_8), messageProperties);
rabbitTemplate.convertAndSend("direct_Exchange", "test4_Queue", message, correlationData);
}
}
当消息队列中的代码积压一会后,执行下面的代码,则会发现消息从优先级大的开始消费
package com.example.demo.mq;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
@Component
public class Test4QueueReceiver {
@RabbitListener(queues = "test4_Queue")
public void process(String mes, Channel channel, Message message) {
System.err.println(mes);
//消息的所有相关信息都可以在message中找到
System.err.println(message.toString());
}
}
注意:
只有当消费者消费能力不足,即消息无法被及时消费而阻塞的时候,优先队列才会根据优先级来分配任务的执行顺序。否则还是先到先消费
/**
* 声明死信交换机
* @return DirectExchange
*/
@Bean
public DirectExchange dlxExchange() {
return new DirectExchange("dlxExchange", true, false);
}
/**
* 声明死信队列
* @return Queue
*/
@Bean
public Queue dlxQueue() {
return new Queue("dlxQueue",true,false,false);
}
/**
* 绑定死信队列到死信交换机
* @return Binding
*/
@Bean
public Binding binding() {
return BindingBuilder.bind(dlxQueue()).to(dlxExchange()).with(dlxQueue().getName());
}
/**
* 声明定长队列,并定义对应的死信交换机
* @return
*/
@Bean
public Queue test5Queue() {
Map<String, Object> map = new HashMap<>();
// 队列中的消息最多只能有两个,如果超过,则先放入队列的消息会被删除投递到死信交换机。
map.put("x-max-length", 2);
//死信交换机的名称
map.put("x-dead-letter-exchange",dlxExchange().getName());
//死信交换机和死信队列绑定的routingKey
map.put("x-dead-letter-routing-key",dlxQueue().getName());
return new Queue("test5_Queue",true,false,false,map);
}
/**
* 交换机与队列绑定
* @return
*/
@Bean
Binding test5Binding(){
return BindingBuilder.bind(test5Queue()).to(directExchange()).with(test5Queue().getName());
}
队列设置成定长队列会有Lim标识
队列绑定了死信队列会有DLX、DLK标识
@GetMapping("/sendMes")
public void sendMes() {
rabbitTemplate.convertAndSend("direct_Exchange", "test5_Queue", "hehehhe");
}
当队列中的消息个数超过两个时,先放入队列的消息会被删除投递到死信交换机,死信交换机会根据routingKey发送到死信队列
也就是间接的实现延迟队列,最后消费者监听的是死信队列