1. 実施原則
キュー ttl + デッド レター交換
の簡単な説明: 2 つのキューを使用します。1 つのキューはメッセージを消費せずに受信します。指定された時間待機した後、メッセージは消滅し、その後キューにバインドされたデッド レター交換がメッセージを別のキューに再度ルーティングして提供します。ビジネス消費。
ttl: x-message-ttl メッセージの生存時間
2. 実現
- スイッチとキューを宣言する
@SpringBootConfiguration
public class RabbitDelayConfig {
/**
* 死信队列
*/
public static final String DEAD_QUEUE = "dead.queue";
/**
* 延时队列
*/
public static final String DELAY_QUEUE = "delay.queue";
/**
* 死信交换机
*/
public static final String DEAD_EXCHANGE = "dead.exchange";
/**
* 原交换机
*/
public static final String DELAY_EXCHANGE = "delay.exchange";
/**
* 声明延时队列(生产者投递消息)
*
*
* @return
*/
@Bean
public Queue getDelayQueue() {
//参数一:队列名称;参数二:队列中消息存活时间(单位ms);参数三:消息过期转发的死信交换机;参数四:死信队列和死信交换机绑定的rootingKey
Queue queue = QueueBuilder.durable(DELAY_QUEUE).ttl(10 * 1000).deadLetterExchange(DEAD_EXCHANGE).deadLetterRoutingKey("deadKey").build();
return queue;
}
/**
* 声明死信队列(接收过期转发消息)
*
* @return
*/
@Bean
public Queue getDeadQueue() {
return new Queue(DEAD_QUEUE, true);
}
/**
* 死信交换机(转发消息到死信队列)
*
* @return
*/
@Bean
public DirectExchange deadExchange() {
DirectExchange exchange = new DirectExchange(DEAD_EXCHANGE, true, false);
return exchange;
}
/**
* 原交换机(投递消息到延时队列)
*
* @return
*/
@Bean
public DirectExchange delayExchange() {
DirectExchange exchange = new DirectExchange(DELAY_EXCHANGE, true, false);
return exchange;
}
/**
* 绑定死信队列和死信交换机
*
* @return
*/
@Bean
public Binding bindDeadExchangeQueue() {
Binding binding = BindingBuilder.bind(getDeadQueue()).to(deadExchange()).with("deadKey");
return binding;
}
/**
* 绑定延时队列和原交换机
*
* @return
*/
@Bean
public Binding bindDelayExchangeQueue() {
Binding binding = BindingBuilder.bind(getDelayQueue()).to(delayExchange()).with("delay-routingKey");
return binding;
}
}
- プロデューサーの作成
@SpringBootTest
@RunWith(SpringRunner.class)
public class DelayMqTest {
@Resource
private RabbitTemplate rabbitTemplate;
@Test
public void send() {
rabbitTemplate.convertAndSend(RabbitDelayConfig.DELAY_EXCHANGE, "delay-routingKey", "延时消息");
System.out.println("发送消息时间:" + System.currentTimeMillis());
}
- コンシューマを作成します (リスニング キューはデッド レター キューです)。
@Component
public class DelayConsumer {
@RabbitListener(queues = RabbitDelayConfig.DEAD_QUEUE)
public void listenDead1(String message) {
System.out.println("接收时间:" + System.currentTimeMillis());
System.out.println("消费者一接收消息:" + message);
}
}
結果:
メッセージの受信時間とメッセージの送信時間は、設定したメッセージ生存時間と基本的に一致していることがわかります。
3. さらに
メッセージの生存時間を設定するには 2 つの方法があります:
1. 遅延キューの作成時に設定します。ここで設定すると、キュー内のすべてのメッセージの生存時間が同じになります。
@Bean
public Queue getDelayQueue() {
Queue queue = QueueBuilder.durable(DELAY_QUEUE).ttl(10 * 1000).deadLetterExchange(DEAD_EXCHANGE).deadLetterRoutingKey("deadKey").build();
return queue;
}
2. メッセージ送信時に設定します。ここで設定すると、キュー内のメッセージの生存時間が異なります。
@Test
public void send1() {
rabbitTemplate.convertAndSend(RabbitDelayConfig.DELAY_EXCHANGE, "delay-routingKey", "延时消息1111", message -> {
message.getMessageProperties().setExpiration(20 * 1000 + "");
return message;
});
System.out.println("发送消息时间:" + System.currentTimeMillis());
}
特に、両方にメッセージ生存時間が設定されている場合、実際のメッセージ生存時間はメッセージの送信時に指定されます。上記のコードでは、実際のメッセージ生存時間は 20000 ミリ秒です。