RabbitMQ --- デッドレター交換

1. はじめに

1.1. デッドレタースイッチとは

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

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

  • コンシューマは、basic.reject または Basic.nack を使用して消費の失敗を宣言し、メッセージの requeue パラメータが false に設定されます。

  • メッセージは期限切れのメッセージです。タイムアウト後は誰も消費しません

  • 配信するキューメッセージがいっぱいのため配信できません

 

デッド レターを含むキューがdead-letter-exchange属性で構成され、スイッチが指定されている場合、キュー内のデッド レターはこのスイッチに配信され、このスイッチはデッド レター交換(Dead Letter Exchange、DLX を確認) と呼ばれます。

 

図に示すように、メッセージはコンシューマによって拒否され、デッドレターになります。

simple.queue はデッド レター交換 dl.direct にバインドされているため、デッド レターはこの交換に配信されます。  

デッド レター スイッチもキューにバインドされている場合、メッセージは最終的にデッド レターが保存されているキューに入ります。  

さらに、キューがデッド レターをデッド レター エクスチェンジに配信するとき、次の 2 つの情報を知っている必要があります。

  • デッドレタースイッチ名

  • デッドレター交換およびデッドレターキューにバインドされた RoutingKey

この方法によってのみ、配信されたメッセージがデッド レター交換に到達し、デッド レター キューに正しくルーティングされることが保証されます。

 

 

1.2. デッドレタースイッチを使用してデッドレターを受信する(拡張)

失敗の再試行戦略では、デフォルトの RejectAndDontRequeueRecoverer は、ローカル再試行回数を使い果たした後、RabbitMQ に拒否を送信し、メッセージはデッドレターになって破棄されます。

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

コンシューマ サービスでは、デッド レター スイッチとデッド レター キューのセットを定義します。  

// 声明普通的 simple.queue队列,并且为其指定死信交换机:dl.direct
@Bean
public Queue simpleQueue2(){
    return QueueBuilder.durable("simple.queue") // 指定队列名称,并持久化
        .deadLetterExchange("dl.direct") // 指定死信交换机
        .build();
}
// 声明死信交换机 dl.direct
@Bean
public DirectExchange dlExchange(){
    return new DirectExchange("dl.direct", true, false);
}
// 声明存储死信的队列 dl.queue
@Bean
public Queue dlQueue(){
    return new Queue("dl.queue", true);
}
// 将死信队列 与 死信交换机绑定
@Bean
public Binding dlBinding(){
    return BindingBuilder.bind(dlQueue()).to(dlExchange()).with("simple");
}

 

1.3. 概要

どのようなメッセージがデッドレターになりますか?

  • メッセージがコンシューマによって拒否されるか、Nack が返されます。

  • メッセージがタイムアウトになり、消費されませんでした

  • キューがいっぱいです

デッドレター交換の使用シナリオは何ですか?

  • キューがデッド レター交換にバインドされている場合、デッド レターはデッド レター交換に配信されます。

  • デッド レター スイッチを使用すると、コンシューマが処理できなかったすべてのメッセージ (デッド レター) を収集し、手動処理に引き渡すことで、メッセージ キューの信頼性をさらに向上させることができます。

 

 

2、TTL

キュー内のメッセージがタイムアウト後に消費されない場合、そのメッセージはデッドレターになります。タイムアウトには 2 つのケースがあります。

  • メッセージが配置されているキューにはタイムアウトが設定されています

  • メッセージ自体がタイムアウトを設定します

 

2.1. タイムアウトデッドレターを受信するデッドレタースイッチ

コンシューマ サービスの SpringRabbitListener で、新しいコンシューマを定義し、デッド レター スイッチとデッド レター キューを宣言します。

@RabbitListener(bindings = @QueueBinding(
    value = @Queue(name = "dl.ttl.queue", durable = "true"),
    exchange = @Exchange(name = "dl.ttl.direct"),
    key = "ttl"
))
public void listenDlQueue(String msg){
    log.info("接收到 dl.ttl.queue的延迟消息:{}", msg);
}

 

2.2. キューの宣言とTTLの指定

キューのタイムアウトを設定するには、キューを宣言するときに x-message-ttl 属性を構成する必要があります。

@Bean
public Queue ttlQueue(){
    return QueueBuilder.durable("ttl.queue") // 指定队列名称,并持久化
        .ttl(10000) // 设置队列的超时时间,10秒
        .deadLetterExchange("dl.ttl.direct") // 指定死信交换机
        .build();
}

このキューはデッドレター スイッチを次のように設定することに注意してください。dl.ttl.direct

スイッチを宣言し、ttl をスイッチにバインドします。

@Bean
public DirectExchange ttlExchange(){
    return new DirectExchange("ttl.direct");
}
@Bean
public Binding ttlBinding(){
    return BindingBuilder.bind(ttlQueue()).to(ttlExchange()).with("ttl");
}

メッセージを送信しますが、TTL は指定しません。

@Test
public void testTTLQueue() {
    // 创建消息
    String message = "hello, ttl queue";
    // 消息ID,需要封装到CorrelationData中
    CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
    // 发送消息
    rabbitTemplate.convertAndSend("ttl.direct", "ttl", message, correlationData);
    // 记录日志
    log.debug("发送消息成功");
}

送信メッセージのログ:

受信したメッセージのログを表示します。  

キューの TTL 値は 10000ms、つまり 10 秒であるためです。メッセージの送信と受信の時間差がちょうど 10 秒であることがわかります。  

 

2.3. メッセージ送信時にTTLを設定する

メッセージを送信するときに、TTL を指定することもできます。

@Test
public void testTTLMsg() {
    // 创建消息
    Message message = MessageBuilder
        .withBody("hello, ttl message".getBytes(StandardCharsets.UTF_8))
        .setExpiration("5000")
        .build();
    // 消息ID,需要封装到CorrelationData中
    CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
    // 发送消息
    rabbitTemplate.convertAndSend("ttl.direct", "ttl", message, correlationData);
    log.debug("发送消息成功");
}

送信されたメッセージのログを表示します。

メッセージログの受信:  

今回は、送信と受信の間の遅延はわずか 5 秒でした。キューとメッセージの両方に TTL が設定されている場合、期限切れのものはデッドレターになることに注意してください。  

 

2.4. 概要

メッセージのタイムアウトには 2 つの方法がありますか?

  • キューに ttl 属性を設定すると、キューに入った後に ttl 時間を超えたメッセージはデッドレターになります

  • メッセージに ttl 属性を設定すると、ttl 時間を超えてメッセージを受信するとキューはデッドレターになります。

消費者がメッセージを送信してから 20 秒後にメッセージを受信したことをどのように認識すればよいでしょうか?

  • メッセージの宛先キューのデッドレター交換を指定します

  • コンシューマがリッスンするキューをデッドレター交換にバインドします

  • メッセージを送信するときは、メッセージのタイムアウト時間を 20 秒に設定します。

 

 

3. 遅延キュー

TTL とデッドレター スイッチを組み合わせて使用​​することで、コンシューマがメッセージの送信後に受信を遅らせる効果が得られました。このメッセージモードを遅延キュー(Delay Queue)モードと呼びます。

遅延キューの使用例には次のものがあります。

  • SMS送信の遅延

  • ユーザーが注文し、15分以内に支払いがない場合、注文は自動的にキャンセルされます

  • 仕事の会議をスケジュールし、20 分後にすべての参加者に自動的に通知します

遅延キューに対する需要が非常に多いため、RabbitMQ は遅延キュー効果をネイティブにサポートするプラグインを正式にリリースしました。

このプラグインは DelayExchange プラグインです。RabbitMQ のプラグイン リスト ページを参照してください: Community Plugins — RabbitMQ

使用方法については、公式 Web サイトのアドレスを参照してください: RabbitMQ でメッセージをスケジュールする | RabbitMQ - Blog

 

3.1. DelayExchange プラグインのインストール

MQ をインストールする


次のコマンドを実行して MQ コンテナを実行します。

docker run \
 -e RABBITMQ_DEFAULT_USER=itcast \
 -e RABBITMQ_DEFAULT_PASS=123321 \
 -v mq-plugins:/plugins \
 --name mq \
 --hostname mq1 \
 -p 15672:15672 \
 -p 5672:5672 \
 -d \
 rabbitmq:3.8-management

DelayExchangeプラグインをインストールする


公式インストール ガイドのアドレスは次のとおりです: RabbitMQ を使用したメッセージのスケジュール | RabbitMQ - ブログ

上記のドキュメントは、RabbitMQ を Linux にネイティブにインストールし、その後プラグインをインストールすることに基づいています。

 

以前にDockerベースでRabbitMQをインストールしたので、今回はDockerベースでRabbitMQプラグインをインストールする方法を説明します。


プラグインをダウンロード


RabbitMQ には、次の場所に公式プラグイン コミュニティがあります: Community Plugins — RabbitMQ

これには、これから使用する DelayExchange プラグインを含む、さまざまなプラグインが含まれています。

 

対応する GitHub ページに移動して、プラグインの 3.8.9 バージョンをダウンロードできます。アドレスは、リリース v3.8.9 Rabbitmq/rabbitmq-layed-message-exchange GitHubです。これは、RabbitMQ バージョン 3.8.5 以降に対応します。


プラグインをアップロードする


Dockerベースでインストールしているため、最初にRabbitMQプラグインディレクトリに相当するデータ量を確認する必要があります。Docker ベースでない場合は、Docker コンテナを再作成します。

前に設定した RabbitMQ のデータ ボリューム名は であるmq-pluginsため、次のコマンドを使用してデータ ボリュームを表示します。

docker volume inspect mq-plugins

次の結果が得られます。

次に、プラグインをこのディレクトリにアップロードします。

 


プラグインをインストールする


最後にインストールされますが、インストールを実行するには MQ コンテナ内に入る必要があります。私のコンテナの名前は なのでmq、次のコマンドを実行します。

docker exec -it mq bash

実行する際-itmq以下を自分のコンテナ名に置き換えてください。

コンテナに入ったら、次のコマンドを実行してプラグインを有効にします。

rabbitmq-plugins enable rabbitmq_delayed_message_exchange

 

3.2. DelayExchangeの原理

DelayExchange では、交換が遅延していると宣言される必要があります。lateExchange にメッセージを送信するときのフローは次のとおりです。

  • メッセージを受信する

  • メッセージに x-delay 属性があるかどうかを判断する

  • x-lay 属性がある場合、それはハード ディスクに永続化される遅延メッセージであることを意味し、x-lay 値が遅延時間として読み取られます。

  • ルーティングが見つからないという結果をメッセージ送信者に返します

  • x 遅延時間が経過した後、指定されたキューにメッセージを再配信します。

 

3.3. DelayExchange の使用

プラグインの使用も非常に簡単です。スイッチを宣言します。スイッチのタイプは任意で、遅延属性を true に設定し、それをバインドするキューを宣言するだけです。

1) DelayExchange スイッチを宣言します

注釈ベース (推奨):

@Bean に基づくこともできます。  

 

2) メッセージを送信する

メッセージを送信するときは、遅延時間を指定するために x-delay 属性を必ず指定してください。

 

3.4. 概要

遅延キュープラグインを使用する手順は何ですか?

• スイッチを宣言し、delayed 属性を true に追加します。

• メッセージを送信するときに、x-lay ヘッダーを追加します。値はタイムアウト時間です。

おすすめ

転載: blog.csdn.net/a1404359447/article/details/130544921