毎日の記録 - SpringBoot は RabbitMQ セクション 5 を統合 (デッドレター)

1. デッドレター

1. デッドレターとは何ですか

キュー内のメッセージが次のいずれかの条件を満たす場合、デッドレターになる可能性があります。

  1. メッセージ TTL の有効期限が切れました。
  2. キューが最大長に達しました (キューがいっぱいで、RabbitMQ にこれ以上データを追加できません)。
  3. メッセージは拒否され (basic.reject または Basic.nack)、メッセージは requeue=false に設定されます (再エンキューしません)。

デフォルトでは、デッドレターは直接破棄されます
ここに画像の説明を挿入

2. 消費の失敗は形骸化する

再試行ポリシー:

  1. RejectAndDontRequeueRecoverer: 再試行が完了すると、直接拒否され、メッセージが失われます。デフォルトの処理戦略です
  2. ImmediateRequeueMessageRecoverer: 再試行が完了すると、nack が返され、メッセージが再度キューに入れられます。
  3. RepublishMessageRecoverer: 再試行が完了した後、指定された交換に失敗メッセージを配信します。

失敗の再試行戦略では、デフォルトの RejectAndDontRequeueRecoverer は、ローカル再試行回数を使い果たした後、RabbitMQ に拒否を送信し、メッセージはデッドレターになって破棄されます。(RepublishMessageRecoverer 戦略を使用する場合は、必ずオフにしてください。オフにしないと、メッセージが戦略にバインドされたキューにスローされる可能性があります)

デッドレター スイッチをキューに追加し、デッドレター キューをデッドレター スイッチにバインドできます。このようにして、メッセージはデッドレターになった後も破棄されず、最終的にデッドレター スイッチに配信され、デッドレター スイッチにバインドされたデッドレター キューにルーティングされます。

3. デッドレタースイッチとデッドレターキューを定義する

デッドレター スイッチとデッドレター キューも一般的なスイッチとキューであるため、次のように定義されます。

import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


//死信交换机和死信队列也是普通的交换机和队列
@Configuration
public class DeadQueueConfig {
    
    

    //定义死信交换机
    @Bean
    public DirectExchange deadLetterExchange() {
    
    
        return ExchangeBuilder.directExchange("dead.letter.exchange").build();
    }


    //定义死信队列
    @Bean
    public Queue deadLetterQueue() {
    
    
        return new Queue("dead.letter.queue",true,false,false);
    }

    //交换机和队列绑定
    @Bean
    public Binding deadLetterQueueBinding(Queue deadLetterQueue, DirectExchange deadLetterExchange) {
    
    
        return BindingBuilder.bind(deadLetterQueue).to(deadLetterExchange).with("dl");
    }
}

4. デッドレタースイッチとキューをバインドする方法

デッドレター交換とデッドレターキューをバインドする

import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;


@Configuration
public class TestDeadQueueConfig {
    
    

    @Bean
    public DirectExchange testDeadLetterExchangeExchange() {
    
    
        return ExchangeBuilder.directExchange("test.dead.letter.exchange").build();
    }



    @Bean
    public Queue testDeadLetterQueue() {
    
    


     return QueueBuilder.durable("test.dead.letter.queue")
             //test.dead.letter.queue队列绑定死信交换机
             .deadLetterExchange("dead.letter.exchange")
             //死信交换机和死信队列绑定 routingKey = dl
             .deadLetterRoutingKey("dl")
             .build();

        /*Map<String, Object> args = new HashMap();
        // DLX(死信交换机)
        args.put("x-dead-letter-exchange", "死信队列交换机的名称");
        // DLK(死信路由key)
        args.put("x-dead-letter-routing-key", "死信消息路由的routingKey");
        // TTL(time-to-live存活时间)
        args.put("x-message-ttl", 10000);
        return new Queue("test.dead.letter.queue",true,false,false,args);*/

    }

    //交换机和队列绑定
    @Bean
    public Binding testDeadLetterQueueBinding(Queue testDeadLetterQueue, DirectExchange testDeadLetterExchangeExchange) {
    
    
        return BindingBuilder.bind(testDeadLetterQueue).to(testDeadLetterExchangeExchange).with("test.dead.letter");
    }
}

ここに画像の説明を挿入

5. メッセージが失敗すると、デッドレターに配信されます。

模擬プロデューサー

import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class DeadQueueTest {
    
    

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Test
    void test(){
    
    
       //模拟生产者
       rabbitTemplate.convertAndSend("test.dead.letter.exchange","test.dead.letter","进行死信测试");


    }
}

模擬消費者


import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
public class DeadQueueListener {
    
    

    @RabbitListener(queues = "test.dead.letter.queue")
    public void testDeadLetterQueueMsg(String msg){
    
    

        System.out.println("test.dead.letter.queue收到消息:"+msg);

        //模拟:处理消息中出现了异常
        int i = 1/0;

        System.out.println("消息处理完毕!");
    }
}

ここに画像の説明を挿入
ここに画像の説明を挿入
メッセージは配信不能キューに正常に配信されました

6. メッセージがタイムアウトになり、デッドレターに配信される

デフォルトでは、メッセージは期限切れになりません。メッセージの期限切れに関連するパラメータを設定しない場合、メッセージは期限切れになりません。メッセージが消費されない場合でも、メッセージは常にキューに保存されます。

TTL が設定されている場合、メッセージはこの時間を超えると自動的に削除されます。

  1. キューのプロパティによって設定: キュー内のすべてのメッセージの有効期限が同じになります
  2. メッセージを個別に設定します: 各メッセージの TTL は異なる場合があります
  3. 両方の方法を同時に使用すると、有効期限は最小値に従います。

1. デッドレターキューに配信されるデモキュータイムアウトTTL

キューを定義し、有効期限を設定します。

import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class TTLQueueConfig {
    
    


    @Bean
    public DirectExchange ttlExchange(){
    
    
        return ExchangeBuilder.directExchange("ttl.exchange").build();
    }

    //定时队列,设置过期时间,并且绑定死信交换机
    @Bean
    public Queue ttlQueue(){
    
    
        return QueueBuilder.durable("ttl.queue")
                //设置队列的超时时间为10s
                .ttl(10*1000)
                //给队列设置死信交换机,名称为dead.letter.exchange 设置投递死信时的RoutingKey为dl
                .deadLetterExchange("dead.letter.exchange")
                .deadLetterRoutingKey("dl")
                .build();
    }

    @Bean
    public Binding ttlBinding(Queue ttlQueue, DirectExchange ttlExchange){
    
    
        return BindingBuilder.bind(ttlQueue).to(ttlExchange).with("test.ttl.queue");
    }


}

模擬プロデューサー

import org.junit.jupiter.api.Test;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class TTLQueueTest {
    
    

    @Autowired
    private RabbitTemplate rabbitTemplate;

    //模拟生产者
    @Test
    public void test(){
    
    
        rabbitTemplate.convertAndSend("ttl.exchange","test.ttl.queue","这个队列10秒后过期,然后到死信队列");
    }


}

サービス開始後
ここに画像の説明を挿入
、プロデューサーを呼び出します
ここに画像の説明を挿入
ここに画像の説明を挿入

2. デモンストレーション メッセージ タイムアウト TTL、配信不能キューに配信される

テストキュータイムアウトによるキューとデッドレター交換

import org.junit.jupiter.api.Test;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.time.LocalTime;

@SpringBootTest
public class TTLQueueTest {
    
    

    @Autowired
    private RabbitTemplate rabbitTemplate;

    //模拟生产者
    @Test
    public void testTTLMessage() {
    
    
        String msgStr = "消息TTL demo,发送时间是:" + LocalTime.now();

        Message message = MessageBuilder
                .withBody(msgStr.getBytes())
                //设置消息TTL为5秒
                .setExpiration("5000")
                .build();

        //发送消息时:
        //  如果消息和队列都设置了TTL,则哪个TTL短,哪个生效
        //  如果消息和队列只设置了一个TTL,则直接以设置的为准
        rabbitTemplate.convertAndSend("ttl.exchange", "test.ttl.queue", message);
    }



}

使用シナリオ: ユーザーが注文し、ユーザーが 15 分以内に支払いを行わない場合、注文は自動的にキャンセルされます。

おすすめ

転載: blog.csdn.net/qq407995680/article/details/132142406