优先级队列 顾名思义,具有高优先级的队列具有高的优先权,优先级高的消息具备优先被消费的特权。
可以通过设置队列的 x-max-priority 参数来实现
配置队列 主要填充x-max-priority属性 并设置最高优先级值为10 默认最低为0
/**
* @Description: 消息队列配置类
* @Author: zw
*/
@Configuration
public class RabbitConfig {
@Bean
Queue priority_Queue() {
Map<String, Object> map = new HashMap<String, Object>(1);
map.put("x-max-priority", 10);
return new Queue("queue.priority", true, false, false, map);
}
@Bean
DirectExchange myExchange() {
return new DirectExchange("myExchange");
}
@Bean
public Binding myBindingPriority() {
return new Binding("queue.priority", Binding.DestinationType.QUEUE, "myExchange", "priority", null);
}
}
配置发送端 我们通过传入的age值来进行不同优先级消息的发放
/**
* author:zw
*/
@Component
public class RabbitMQSender implements RabbitTemplate.ConfirmCallback, RabbitTemplate.ReturnCallback {
private static final Logger logger = LoggerFactory.getLogger(RabbitMQSender.class);
@Autowired
RabbitTemplate rabbitTemplate;
@PostConstruct
public void init() {
rabbitTemplate.setConfirmCallback(this);
rabbitTemplate.setReturnCallback(this);
}
public void sendDirectMsg(Object msg) {
CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
Map<String, Object> map = (HashMap<String, Object>) msg;
System.out.println("消息id" + correlationData.getId() + "-age=" + Integer.parseInt(map.get("age").toString()));
MessagePostProcessor messagePostProcessor = null;
if (Integer.parseInt(map.get("age").toString()) == 1) {
MessagePostProcessor messagePostProcessorInner = message -> {
MessageProperties messageProperties = message.getMessageProperties();
//设置编码
messageProperties.setContentEncoding("utf-8");
//设置过期时间10*1000毫秒
messageProperties.setPriority(1);
return message;
};
messagePostProcessor = messagePostProcessorInner;
} else if (Integer.parseInt(map.get("age").toString()) == 5) {
MessagePostProcessor messagePostProcessorInner = message -> {
MessageProperties messageProperties = message.getMessageProperties();
//设置编码
messageProperties.setContentEncoding("utf-8");
//设置过期时间10*1000毫秒
messageProperties.setPriority(5);
return message;
};
messagePostProcessor = messagePostProcessorInner;
}
rabbitTemplate.convertAndSend("myExchange", "priority", msg, messagePostProcessor, correlationData);
}
}
在这里为了满足演示条件,先不配置消费者,启动服务,通过传入的age值判断分别发送优先级为1的和5的消息
由图可见我是先发送三条优先级为1的消息,后发送三条优先级为5的消息
此时MQ管理插件已经可以看到此队列有优先级属性
等到队列堆积之后,我们配置一个消费者重启服务
/**
* author:zw
*/
@Component
public class RabbitMQConsumer {
@RabbitListener(queues = "queue.priority")
public void queue_priority(Message msg, Channel channel) throws IOException {
System.out.println("进入queue.priority时间为" + new Date().toLocaleString());
if (null != msg && null != msg.getBody() && 0 != msg.getBody().length) {
HashMap<String, Object> map = (HashMap<String, Object>) SerializationUtils.deserialize(msg.getBody());
Object age = map.get("age");
System.out.println("进入消息Age=" + age);
channel.basicAck(msg.getMessageProperties().getDeliveryTag(), false);//消息确认
System.out.println("消息确认");
}
}
}
观察结果如下:
如上图可见 ,因为我代码里面是根据age=1的发送优先级为1的消息 age=5的发送优先级为5的消息,没有设置优先级之前,
先发的age=1三条消息应该被先消费,而配置了优先级之后,优先级值大的被先消费。
优先级高的消息可以被优先消费,这个也是有前提的 如果在消费者的消费速度大于生产者的速度
且Broke 中没有消息堆积的情况下 对发送的消息设置优先级也就没有什么实际意义。因为生产者刚发送完 条消息就被消费者消费了,那么就相当于 Broker 中至多只有一条消息,对于单条消息来说优先级是没有什么意义的。