1、方式一:利用Time To Live(TTL)和Dead Letter Exchanges(DLX)
TTL是指消息的生存时间,RabbitMQ可以针对队列设置x-expires或者针对消息设置x-message-ttl来控制消息的生存时间。如果消息超时,则变为dead letter(死信)。DLX是指当队列中出现dead letter时,可以重新路由转发到指定的队列。
具体步骤如下:
- 在pom.xml文件中添加RabbitMQ的依赖。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
2.创建立即消费队列和延时队列例子。
@Configuration
public class RabbitMqConfig {
@Bean
public TopicExchange synCancelOrderDelayExchange(){
TopicExchange topicExchange = new TopicExchange(RabbitConsts.X_DEAD_LETTER_EXCHANGE,true,false);
return topicExchange;
}
@Bean
public Queue synCancelOrderDelaySendQueue() {
/**
durable="true" 持久化 rabbitmq重启的时候不需要创建新的队列
auto-delete 表示消息队列没有在使用时将被自动删除 默认是false
exclusive 表示该消息队列是否只在当前connection生效,默认是false
*/
Map<String, Object> params = new HashMap<>();
// x-dead-letter-exchange 声明了队列里的死信转发到的DLX名称,
params.put(RabbitConsts.X_DEAD_LETTER_EXCHANGE, RabbitConsts.X_DEAD_LETTER_EXCHANGE);
// x-dead-letter-routing-key 声明了这些死信在转发时携带的 routing-key 名称。
params.put(RabbitConsts.X_DEAD_LETTER_ROUTING_KEY,RabbitConsts.X_DEAD_LETTER_ROUTING_KEY);
return new Queue(RabbitConsts.CANCELORDER_QUEUE, true, false, false,params);
}
/**
普通队列
*/
@Bean
public Queue synCancelOrderDelayConsumeQueue() {
/**
durable="true" 持久化 rabbitmq重启的时候不需要创建新的队列
auto-delete 表示消息队列没有在使用时将被自动删除 默认是false
exclusive 表示该消息队列是否只在当前connection生效,默认是false
死信队列里的消息过期后会转到该队列中
*/
return new Queue(RabbitConsts.CANCELORDER_CONSUME_QUEUE, true, false, false);
}
/**
将消息队列1和交换机进行绑定
*/
@Bean
public Binding bindingCancelOrderSend() {
return BindingBuilder.bind(synCancelOrderDelaySendQueue()).to(synCancelOrderDelayExchange()).with(RabbitConsts.CANCELORDER_SEND_ROUTINGKEY);
}
/**
* 将消息队列2和交换机进行绑定
*/
@Bean
public Binding bindingCancelOrderConsume() {
return BindingBuilder.bind(synCancelOrderDelayConsumeQueue()).to(synCancelOrderDelayExchange()).with(RabbitConsts.X_DEAD_LETTER_ROUTING_KEY);
}
}
3. 启动后查看RabbitMQ服务器创建好的队列:
4.创建消息生产者例子。
package com.jzy.service.rabbit.provider;
import com.jzy.consts.RabbitMqConstant;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Component;
import java.nio.charset.StandardCharsets;
@Component
@Slf4j
@RequiredArgsConstructor
public class RabbitMQSendMsgServiceV3 {
private final RabbitTemplate rabbitTemplate;
public void sendMsg() {
try {
Message msg = MessageBuilder.withBody(("哈哈呼呼呼哈哈").getBytes(StandardCharsets.UTF_8)).build();
rabbitTemplate.convertAndSend(
RabbitMqConstant.EXCHANGE_RETRY_SEND_MSG, RabbitMqConstant.RETRY_SEND_MSG_ROUTING_KEY,
msg , message -> {
//设置延迟时间5000毫秒
message.getMessageProperties().setDelay(5000);
return message;
});
log.info("消息发送成功");
} catch (Exception e) {
e.printStackTrace();
log.error("发送消息出现异常", e);
}
}
}
5.消息消费者事例:
package com.jzy.service.rabbit.consumer;
import com.jzy.consts.RabbitMqConstant;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
/**
* 监听设备端没有回复的数据
*/
@Component
@Slf4j
public class MqttRecordMessageListener {
@RabbitListener(queues= RabbitMqConstant.QUEUE_RETRY_DELAY_SEND_MSG)
public void listenerMessage(Message message, Channel channel){
try {
MessageProperties messageProperties = message.getMessageProperties();
//接受发送的json数据
String string = new String(message.getBody());
log.info("这是监听到的数据----->:{}",string);
//手动确认机制
channel.basicAck(messageProperties.getDeliveryTag(),true);
}catch (Exception e){
e.printStackTrace();
log.error("监听MQ队列出现异常。,异常信息为:",e);
}
}
}
2、方式二:利用RabbitMQ插件x-delay-message
RabbitMQ提供了一个插件x-delay-message,可以实现延时消息的发送和消费。
具体步骤如下:
2.1.在配置类中定义延迟交换机,设置自定义参数定义交换机类型和申明交换机中的消息为延迟消息。
package com.jzy.service.rabbit.config;
import com.jzy.consts.RabbitMqConstant;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 消息队列整合
*/
@Configuration
public class RabbitMqConfig {
/**
* 队列名称
* @return
*/
@Bean
public Queue sendMsgQueue() {
return new Queue(RabbitMqConstant.QUEUE_RETRY_DELAY_SEND_MSG,true,false,false);
}
//Direct交换机 起名:TestDirectExchange
/**
* 交换机
* String name, boolean durable, boolean autoDelete
* @return
*/
@Bean
DirectExchange sendMsgExchange() {
DirectExchange directExchange = new DirectExchange(RabbitMqConstant.EXCHANGE_RETRY_SEND_MSG, true, false);
//开启延时队列
directExchange.setDelayed(true);
return directExchange;
}
//绑定 将队列和交换机绑定, 并设置用于匹配键:sendMsgRouting
@Bean
Binding bindingDirect() {
return BindingBuilder.bind(sendMsgQueue()).to(sendMsgExchange()).with(RabbitMqConstant.RETRY_SEND_MSG_ROUTING_KEY);
}
}
- 2.2.创建延迟消息的生产者,设置消息的延时时间。
package com.jzy.service.rabbit.provider;
import com.jzy.consts.RabbitMqConstant;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Component;
import java.nio.charset.StandardCharsets;
@Component
@Slf4j
@RequiredArgsConstructor
public class RabbitMQSendMsgServiceV3 {
private final RabbitTemplate rabbitTemplate;
public void sendMsg() {
try {
Message msg = MessageBuilder.withBody(("哈哈呼呼呼哈哈").getBytes(StandardCharsets.UTF_8)).build();
rabbitTemplate.convertAndSend(
RabbitMqConstant.EXCHANGE_RETRY_SEND_MSG, RabbitMqConstant.RETRY_SEND_MSG_ROUTING_KEY,
msg , message -> {
//设置延迟时间5000毫秒
message.getMessageProperties().setDelay(5000);
return message;
});
log.info("消息发送成功");
} catch (Exception e) {
e.printStackTrace();
log.error("发送消息出现异常", e);
}
}
}
- 2.3.创建延迟消息的消费者,监听延迟队列。
package com.jzy.service.rabbit.consumer;
import com.jzy.consts.RabbitMqConstant;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
/**
* 监听设备端没有回复的数据
*/
@Component
@Slf4j
public class MqttRecordMessageListener {
@RabbitListener(queues= RabbitMqConstant.QUEUE_RETRY_DELAY_SEND_MSG)
public void listenerMessage(Message message, Channel channel){
try {
MessageProperties messageProperties = message.getMessageProperties();
//接受发送的json数据
String string = new String(message.getBody());
log.info("这是监听到的数据----->:{}",string);
//手动确认机制
channel.basicAck(messageProperties.getDeliveryTag(),true);
}catch (Exception e){
e.printStackTrace();
log.error("监听MQ队列出现异常。,异常信息为:",e);
}
}
}
完结:前面有rabbitMQ基础知识篇:RabbitMQ消息队列重要知识点:基础篇:-CSDN博客