web-dev-qa-db-ja.com

RabbitMQデッドレター交換でメッセージが表示されない

私は最初のRabbitMQデッドレター交換をセットアップしようとしています。ウェブ管理インターフェースで使用する手順は次のとおりです。

  1. 「dead.letter.test」という名前の新しいDIRECT交換を作成します
  2. 新しいキュー「dead.letter.queue」を作成します
  3. 「dead.letter.queue」を「dead.letter.test」にバインドします
  4. デッドレター交換を「dead.letter.test」に設定して、新しいキュー「test1」を作成します
  5. 「test1」にメッセージを送信します
  6. 「test1」のメッセージをNack(requeue = falseで)

私は、これらの手順が「dead.letter.test」交換を通じて「dead.letter.queue」にレコードを入れることを期待しています。これは起きていません。

メッセージを手動で「dead.letter.test」交換に入れると、「dead.letter.queue」に表示されるため、問題ないことがわかります。

管理UIを見ると、キュー「test1」にDLXパラメーターが設定されていることがわかります。

どこがおかしいの?

42
jhilden

Gentilissimo Signoreは、Twitterで私の質問に答えてくれました。問題は、デッドレター交換がダイレクトとして設定されている場合、mustデッドレタールーティングキーを指定することです。後で調査するために、すべてのNACKされたメッセージをデッドレターバケットに入れたい場合(私と同じように)、デッドレター交換をFANOUTとして設定する必要があります。

更新された手順は次のとおりです。

  1. 新規作成[〜#〜] fanout [〜#〜]「dead.letter.test」という名前の交換
  2. 新しいキュー「dead.letter.queue」を作成します
  3. 「dead.letter.queue」を「dead.letter.test」にバインドします
  4. デッドレター交換を「dead.letter.test」に設定して、新しいキュー「test1」を作成します
  5. 「test1」にメッセージを送信します
  6. 「test1」のメッセージをNack(requeue = falseで)
59
jhilden

ルーティングキーを使用せず、直接交換するDead Letter Exchange



dead_queue
dead_exchange
dead_queuedead_exchange
test_queuex-dead-letter-exchangedead_exchange
test_exchange
test_exchangetest_queue

そして最後に確認します。このために何かを公開するtest_exchange'引数付き'有効期限'10000に設定します。その後、メッセージが公開されたときに'test_exchange「それは行きます」test_queue'キュー内でメッセージの有効期限が切れると、DLX Parameter(Dead Letter Exchange name)を探し、そのメッセージで名前を見つけます'dead_exchange'そのメッセージが届きます'dead_exchange「配信」デッドキュー'..まだこれに関して問題があり、もし私があなたの問題を理解できなかったら...あなたの問題を書きましょう。

注意: 'にメッセージを公開する必要がありますtest_exchange'そのtest_queueとtest_exchangeバインディングにはルーティングキーがなく、正常に動作しますが、メッセージを'test_queueデフォルトの交換およびルーティングキーが使用されます。メッセージキューの有効期限が切れると、そのデッドメッセージをデフォルトのルーティングキーでdead_exchangeに配信しようとし、メッセージはそのキューに移動しません。

12
Sahil Gulati

デッドレター交換でカスタムルーティングキーを使用する場合は、作業キューを宣言するときにx-dead-letter-routing-keyを設定する必要があります(この場合はtest1です)、そうでない場合はデフォルトのルーティングキーが使用されます。あなたの場合、RabbitMQブローカーはサイクリングを検出し、拒否されたメッセージを単にドロップします。

必要なのは、x-dead-letter-exchange=dead.letter.testおよびx-dead-letter-routing-key=dead.letter.queue引数をtest1キューに設定することです。

6
pinepain

すべてのキューで同じデッドレター交換を使用する場合、一般的なポリシーを設定する方が簡単です。

Sudo rabbitmqctl -p /my/vhost/path set_policy DLX ".*" '{"dead-letter-exchange":"MyExchange.DEAD"}' --apply-to queues
3
cohadar

強制的でない場合は、FANOUT交換を作成する必要はありません。

既に他の交換に使用した同じルーティングキーを使用して、直接交換を作成できます。また、新しい交換のために新しいキューを作成する必要もありません。既存のキューを新しい交換で使用できます。その新しい交換をキューにバインドするだけです。

ここに私のreceive.jsファイルがあります:

var amqp = require("amqplib/callback_api");
var crontab = require('node-crontab');

amqp.connect("amqp://localhost", function (err, conn) {
conn.createChannel(function (err, ch) {
    var ex = 'direct_logs';
    var ex2 = 'dead-letter-test';
    var severity = 'enterprise-1-key';

    //assert "direct" exchange
    ch.assertExchange(ex, 'direct', { durable: true });
    //assert "dead-letter-test" exchange
    ch.assertExchange(ex2, 'direct', { durable: true });

    //if acknowledgement is nack() then message will be stored in second exchange i.e. ex2="dead-letter-test"
    ch.assertQueue('enterprise-11', { exclusive: false, deadLetterExchange: ex2 }, function (err, q) {
        var n = 0;
        console.log(' [*] Waiting for logs. To exit press CTRL+C');
        console.log(q);

        //Binding queue with "direct_logs" exchange
        ch.bindQueue(q.queue, ex, severity);
        //Binding the same queue with "dead-letter-test"
        ch.bindQueue(q.queue, ex2, severity);

        ch.consume(q.queue, function (msg) {
            // consume messages via "dead-letter-exchange" exchange at every second.
            if (msg.fields.exchange === ex2) {
                crontab.scheduleJob("* * * * * *", function () {
                    console.log("Received by latest exchange %s", msg.fields.routingKey, msg.content.toString());
                });
            } else {
                console.log("Received %s", msg.fields.routingKey, msg.content.toString());
            }

            if (n < 1) {
                // this will executes first time only. Here I'm sending nack() so message will be stored in "deadLetterExchange"
                ch.nack(msg, false, false);
                n += 1;
            } else {
                ch.ack(msg)
                n = 0
            }
        }, { noAck: false });
    });
  });
});
3
Jay Sojitra

「dead.letter.test」という名前の新しいDIRECT交換を作成します

正しい

新しいキュー「dead.letter.queue」を作成します

正しい

「dead.letter.queue」を「dead.letter.test」にバインドします

正しい

デッドレター交換を「dead.letter.test」に設定して、新しいキュー「test1」を作成します

Test1キューを作成し、dead.letter.test exchangeにバインドしていると仮定しています

「test1」にメッセージを送信します

Dead.letter.queueでメッセージを受信する場合は、メッセージを送信するときにルーティングキーを指定する必要があり、dead.letter.queueを使用するクライアントも同じルーティングキーを使用する必要があります。

ルーティングキーなしで公開している場合、test1にサブスクライブしているクライアントのみがメッセージを受信します。

メッセージをdirect.letter.test交換に公開すると、すべてのキューがメッセージを受信します。ファンアウト交換のように機能します

したがって、dead.letter.queueでメッセージを受信する場合は、そのキューでメッセージを発行するか、交換するメッセージを発行およびサブスクライブして発行するときに同じルーティングキーを使用する必要があります。

2
Jack Daniel's