这篇是 代码篇 ,略过 Direct,Fanout,Topic 这几种基本队列的使用介绍,但是 Github 仓库上可以查看到的。
图片
<( ̄︶ ̄)↗[GO!]
冲冲冲~
死信队列
死信是指有这三个特点的消息
- 消息被拒绝,且没有重新入队(投递)
- 消息过期
- 消息队列满了
// nack 返回 false,并放弃重新回到队列
channel.basicNack(deliveryTag, false, false);
//拒绝,不重新入队列
channel.basicReject(deliveryTag, false);
死信交换机 —— DLX:Dead-Letter-Exchange
@Bean
public DirectExchange directExchange2() {
/**
* 交换机名,后面两个是默认值就:持久化,不自动删除
*/
return new DirectExchange(RabbitMQConstants.DIRECT_EXCHANGE2, true, false);
}
@Bean
public Queue directQueue2() {
return QueueBuilder
.durable(RabbitMQConstants.DIRECT_QUEUE2)
.deadLetterExchange(RabbitMQConstants.DLX_EXCHANGE)
.deadLetterRoutingKey(RabbitMQConstants.DLX_ROUTING_KEY)
.build();
}
/**
* 将队列绑定到交换机上
*
* @return
*/
@Bean
public Binding directBinding2() {
return BindingBuilder.
bind(directQueue2()).
to(directExchange2()).
with(RabbitMQConstants.DIRECT_BINDING_KEY2);
}
过期时间
两种设置方式
- 创建队列时设置,消息会被排序加入到队列头部,短的在前
- 发送消息时设置,时间到期不会立刻删除,而是在推送消息时删除
同时设置的话,过期时间已短的为准
/**
* 创建队列时设置
* @return
*/
@Bean
public Queue ttlQueue() {
Map<String, Object> args = new HashMap<>();
//设置消息过期时间
args.put("x-message-ttl", 5000);
//设置死信交换机
args.put("x-dead-letter-exchange", RabbitMQConstants.DLX_EXCHANGE);
//设置死信 routing_key
args.put("x-dead-letter-routing-key", RabbitMQConstants.DLX_ROUTING_KEY);
return new Queue(RabbitMQConstants.TTL_QUEUE, true, false, false, args);
}
/**
* 发送消息时设置
* @return
*/
public void sendMessage2() throws JsonProcessingException {
User user = new User();
ObjectMapper objectMapper = new ObjectMapper();
byte[] bytes = objectMapper.writeValueAsBytes(user);
// 10 s 后过期
Message message =
MessageBuilder.withBody(bytes)
.setExpiration("10000").build();
// 交换机,路由键,信息
rabbitTemplate.convertAndSend(
RabbitMQConstants.DIRECT_EXCHANGE2,
RabbitMQConstants.DIRECT_ROUTING_KEY2,
message
);
}
效果演示
图片
队列 5 秒延迟的效果
图片
延迟队列
两种方案实现
- 利用 死信队列+过期时间 去处理,消息过期被转发到死信交换机,死信交换机路由到死信队列进行处理
- 使用插件 rabbitmq_delayed_message_exchange
插件可以在这里找到 👇
https://github.com/rabbitmq/rabbitmq-delayed-message-exchange/releases
图片
其他插件:https://www.rabbitmq.com/community-plugins.html
图片
安装插件步骤
拷贝文件
docker cp . rabbitmq:/plugins
进入容器
docker exec -it rabbitmq /bin/bash
开启插件支持
rabbitmq-plugins enable rabbitmq_delayed_message_exchange
// 延迟交换机
@Bean
public CustomExchange delayedExchange() {
Map<String, Object> args = new HashMap<>();
// 交换机类型
args.put("x-delayed-type", "direct");
return new CustomExchange(RabbitMQConstants.DELAY_EXCHANGE, "x-delayed-message", true, false, args);
}
public void sendMessage() throws JsonProcessingException {
User user = new User();
ObjectMapper objectMapper = new ObjectMapper();
byte[] bytes = objectMapper.writeValueAsBytes(user);
//延迟 10 s
Message message = MessageBuilder.withBody(bytes).setHeader("x-delay", 10_000).build();
// 交换机,路由键,信息
rabbitTemplate.convertAndSend(
RabbitMQConstants.DELAY_EXCHANGE,
RabbitMQConstants.DELAY_ROUTING_KEY,
message
);
}
效果演示
图片
10 秒的延迟
图片
优先级队列
x-max-priority 可以设置在队列和消息上
- 设置在队列上,表示该队列是个 优先级队列,同时,消息的最大优先级无法超过队列设置的上限
- 发送消息时,带上优先级,在 消息堆积的情况下,优先级 高的 会先被消费 ;
@Bean
public Queue directPriorityQueue() {
Map<String, Object> args = new HashMap<>();
// 最大优先级
args.put("x-max-priority", 10);
return new Queue(RabbitMQConstants.PRIORITY_QUEUE, true, false, false, args);
}
public void sendMessage() throws Exception {
User user = new User();
ObjectMapper objectMapper = new ObjectMapper();
// 交换机,路由键,信息, 优先级 5
retryRabbitTemplate.convertAndSend(
RabbitMQConstants.PRIORITY_EXCHANGE,
RabbitMQConstants.PRIORITY_ROUTING_KEY,
MessageBuilder.withBody( objectMapper.writeValueAsBytes(user.setPriority(5))).setPriority(5).build()
);
}
效果演示
图片
先营造消息堆积的场景 👇
图片
开始消费 👇
图片
那么,就简单介绍到这里了。
我的 GitHub 地址:https://github.com/Java4ye/springboot-demo-4ye
图片