私は最初のRabbitMQデッドレター交換をセットアップしようとしています。ウェブ管理インターフェースで使用する手順は次のとおりです。
私は、これらの手順が「dead.letter.test」交換を通じて「dead.letter.queue」にレコードを入れることを期待しています。これは起きていません。
メッセージを手動で「dead.letter.test」交換に入れると、「dead.letter.queue」に表示されるため、問題ないことがわかります。
管理UIを見ると、キュー「test1」にDLXパラメーターが設定されていることがわかります。
どこがおかしいの?
Gentilissimo Signoreは、Twitterで私の質問に答えてくれました。問題は、デッドレター交換がダイレクトとして設定されている場合、mustデッドレタールーティングキーを指定することです。後で調査するために、すべてのNACKされたメッセージをデッドレターバケットに入れたい場合(私と同じように)、デッドレター交換をFANOUTとして設定する必要があります。
更新された手順は次のとおりです。
そして最後に確認します。このために何かを公開する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に配信しようとし、メッセージはそのキューに移動しません。
デッドレター交換でカスタムルーティングキーを使用する場合は、作業キューを宣言するときにx-dead-letter-routing-key
を設定する必要があります(この場合はtest1
です)、そうでない場合はデフォルトのルーティングキーが使用されます。あなたの場合、RabbitMQブローカーはサイクリングを検出し、拒否されたメッセージを単にドロップします。
必要なのは、x-dead-letter-exchange=dead.letter.test
およびx-dead-letter-routing-key=dead.letter.queue
引数をtest1
キューに設定することです。
すべてのキューで同じデッドレター交換を使用する場合、一般的なポリシーを設定する方が簡単です。
Sudo rabbitmqctl -p /my/vhost/path set_policy DLX ".*" '{"dead-letter-exchange":"MyExchange.DEAD"}' --apply-to queues
強制的でない場合は、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 });
});
});
});
「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でメッセージを受信する場合は、そのキューでメッセージを発行するか、交換するメッセージを発行およびサブスクライブして発行するときに同じルーティングキーを使用する必要があります。