J'essaie de configurer mon premier échange de lettres mortes RabbitMQ, voici les étapes que j'utilise via l'interface d'administration Web:
Je m'attends à ce que ces étapes mettent un enregistrement dans "dead.letter.queue" via l'échange "dead.letter.test". Cela n'arrive pas.
Je peux manuellement mettre un message dans l'échange "dead.letter.test" et il apparaît dans "dead.letter.queue" donc je sais que c'est très bien.
Lorsque je regarde l'interface utilisateur d'administration, cela montre que le paramètre DLX est configuré sur la file d'attente "test1".
Où vais-je mal?
Gentilissimo Signore a eu la gentillesse de répondre à ma question sur Twitter. Le problème est que si votre échange de lettres mortes est configuré en DIRECT vous devez spécifier une clé de routage de lettres mortes. Si vous souhaitez simplement que tous vos messages NACK soient placés dans un seau de lettres mortes pour une enquête ultérieure (comme je le fais), votre échange de lettres mortes doit être configuré en tant que FANOUT.
Voici les étapes mises à jour qui fonctionnent:
Et enfin nous allons le vérifier. Pour cela, publiez quelque chose sur 'test_exchange"avec argument"expiration"défini sur 10000. Après cela, lorsqu'un message est publié sur"test_exchange"ça ira"test_queue"et lorsqu'un message arrive à expiration dans une file d'attente, il recherche le paramètre DLX (nom Dead Letter Exchange) dans lequel ce message trouve le nom"dead_exchange"alors ce message atteindra"dead_exchange"livrer à"file d'attente morte'.. Si vous avez toujours un problème à ce sujet et si je ne comprends pas votre problème ... écrivez votre problème, je vais sûrement l'examiner ... Merci ..
Remarque: Doit publier le message sur 'test_exchange"car cette liaison test_queue et test_exchange est sans clé de routage et cela fonctionnera bien mais si vous publiez un message sur"test_queue'la clé d'échange et de routage par défaut sera utilisée.Après l'expiration de la file d'attente de messages, il tentera de remettre ce message mort à dead_exchange avec une clé de routage par défaut et le message n'ira pas dans cette file d'attente.
Si vous souhaitez utiliser une clé de routage personnalisée sur l'échange de lettres mortes, vous devez définir x-dead-letter-routing-key
lors de la déclaration de la file d'attente de travail (dans votre cas, c'est test1
), sinon la clé de routage par défaut sera utilisée. Dans votre cas, le courtier RabbitMQ détecte le cyclage et laisse simplement tomber les messages rejetés.
Ce dont vous avez besoin, c'est d'avoir x-dead-letter-exchange=dead.letter.test
et x-dead-letter-routing-key=dead.letter.queue
arguments définis sur test1
file d'attente.
Si vous souhaitez que toutes vos files d'attente aient le même échange de lettres mortes, il est plus facile de définir une stratégie générale:
Sudo rabbitmqctl -p /my/vhost/path set_policy DLX ".*" '{"dead-letter-exchange":"MyExchange.DEAD"}' --apply-to queues
Pas besoin de créer un échange FANOUT s'il n'est pas obligatoire.
Vous pouvez créer un échange DIRECT en utilisant la même clé de routage que vous avez déjà utilisée pour un autre échange. Et pas besoin non plus de créer une nouvelle file d'attente pour le nouvel échange. Vous pouvez utiliser les files d'attente existantes avec un nouvel échange. Vous avez juste besoin de lier ce nouvel échange à la file d'attente.
Voici mon fichier 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 });
});
});
});
Créer un nouvel échange DIRECT avec le nom "dead.letter.test"
Correct
Créer une nouvelle file d'attente "dead.letter.queue"
Correct
Liez "dead.letter.queue" à "dead.letter.test"
Correct
Créer une nouvelle file d'attente "test1" avec l'échange de lettres mortes défini sur "dead.letter.test"
Je suppose que vous créez la file d'attente test1 et la liez à l'échange dead.letter.test
Envoyer un message dans "test1"
Si vous souhaitez que votre message soit reçu par dead.letter.queue, vous devrez fournir une clé de routage lors de l'envoi du message et les clients consommant dead.letter.queue doivent également utiliser la même clé de routage
Si vous publiez sans clé de routage, seuls les clients abonnés à test1 recevront le message.
Si vous publiez un message sur l'échange direct.letter.test, alors toute la file d'attente recevra le message. Cela fonctionnera comme un échange de fanout
Donc, si vous souhaitez que dead.letter.queue reçoive un message, vous devrez publier le message dans cette file d'attente ou vous devrez utiliser la même clé de routage lors de la publication et de l'abonnement et publier le message à échanger.