El intercambio de cartas muertas de RabbitMQ nunca recibe mensajes
dead-letter (6)
Estoy tratando de configurar mi primer intercambio de cartas muertas de RabbitMQ, aquí están los pasos que estoy usando a través de la interfaz de administración web:
- Crea un nuevo intercambio DIRECTO con el nombre "dead.letter.test"
- Crear nueva cola "dead.letter.queue"
- Enlace "dead.letter.queue" a "dead.letter.test"
- Cree una nueva cola "test1" con el intercambio de letras muertas establecido en "dead.letter.test"
- Enviar un mensaje a "test1"
- Nack (con requeue = falso) el mensaje en "test1"
Estoy esperando que estos pasos pongan un registro en el "dead.letter.queue" a través del intercambio "dead.letter.test". Esto no está ocurriendo.
Puedo poner manualmente un mensaje en el intercambio "dead.letter.test" y aparece en "dead.letter.queue", así que sé que está bien.
Cuando miro la IU de administración, se muestra que el parámetro DLX está configurado en la cola "test1".
¿Dónde estoy equivocado?
Crea un nuevo intercambio DIRECTO con el nombre "dead.letter.test"
Correcto
Crear nueva cola "dead.letter.queue"
Correcto
Enlazar "dead.letter.queue" a "dead.letter.test"
Correcto
Cree la nueva cola "test1" con el intercambio de letras muertas establecido en "dead.letter.test"
Supongo que está creando una cola de prueba 1 y la está enlazando a dead.letter.test exchange
Enviar un mensaje a "test1"
Si desea que su mensaje sea recibido por dead.letter.queue, deberá proporcionar la clave de enrutamiento al enviar el mensaje y los clientes que consuman dead.letter.queue también debería usar la misma clave de enrutamiento
Si está publicando sin clave de enrutamiento, solo los clientes suscritos a test1 recibirán el mensaje.
Si publica un mensaje en el intercambio de direct.letter.test, toda la cola recibirá el mensaje. Funcionará como un intercambio de fanout.
Entonces, si quieres que dead.letter.queue reciba el mensaje, tendrás que publicar el mensaje en esa cola o tendrás que usar la misma clave de enrutamiento mientras publicas y suscribes y publicas un mensaje para intercambiar.
Gentilissimo Signore tuvo la amabilidad de responder mi pregunta en Twitter. El problema es que si su intercambio de cartas muertas se configura como DIRECTO, debe especificar una clave de enrutamiento de letras muertas. Si solo desea que todo su mensaje NACKed entre en un paquete de cartas muertas para una investigación posterior (como lo hago yo), entonces su intercambio de cartas muertas debe configurarse como un FANOUT.
Aquí están los pasos actualizados que funcionan:
- Crea un nuevo intercambio de FANOUT con el nombre "dead.letter.test"
- Crear nueva cola "dead.letter.queue"
- Enlace "dead.letter.queue" a "dead.letter.test"
- Cree la nueva cola "test1" con el intercambio de letras muertas establecido en "dead.letter.test"
- Enviar un mensaje a "test1"
- Nack (con requeue = false) el mensaje en "test1"
No es necesario crear un intercambio FANOUT si no es obligatorio.
Puede crear un intercambio DIRECTO utilizando la misma clave de enrutamiento que ya ha utilizado para otro intercambio. Y tampoco es necesario crear una nueva cola para el nuevo intercambio. Puede usar colas existentes con nuevo intercambio. Solo necesitas vincular ese nuevo intercambio con la cola.
Aquí está mi archivo 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 });
});
});
});
Si desea que todas sus colas tengan el mismo intercambio de cartas muertas, es más fácil establecer una política general:
sudo rabbitmqctl -p /my/vhost/path set_policy DLX ".*" ''{"dead-letter-exchange":"MyExchange.DEAD"}'' --apply-to queues
Si desea utilizar la clave de enrutamiento personalizada en el intercambio de letras muertas, debe establecer x-dead-letter-routing-key
al declarar la cola de trabajo (en su caso es test1
), de lo contrario se usará la clave de enrutamiento predeterminada. En su caso, el intermediario RabbitMQ detecta el ciclo y simplemente descarta los mensajes rechazados.
Lo que necesita es tener x-dead-letter-exchange=dead.letter.test
y x-dead-letter-routing-key=dead.letter.queue
arguments establecidos en test1
queue.
Dead Letter Exchange sin clave de enrutamiento y con intercambio directo
Siga los pasos que estos funcionarán con seguridad:
1. Crea una nueva cola llamada '' dead_queue ''.
2. Cree un intercambio llamado '' dead_exchange '' y el tipo de intercambio debe ser ''directo''.
3. Vincule '' dead_queue '' y '' dead_exchange '' sin la clave de enrutamiento.
4. Cree una nueva cola llamada '' test_queue '' y establezca su nombre '' x-dead-letter-exchange '' como '' dead_exchange ''
5. Cree un intercambio llamado '' test_exchange '' y el tipo de intercambio debe ser ''directo''
6. Enlazar '' test_exchange '' y '' test_queue '' sin clave de enrutamiento.
Y por fin lo comprobaremos. Para esto, publique algo en '' test_exchange '' con el argumento '' expiration '' establecido en 10000. Después de esto, cuando se publique un mensaje en '' test_exchange '' irá a '' test_queue '' y cuando un mensaje expire en una cola buscará DLX Parámetro (nombre de Dead Letter Exchange) allí ese mensaje encuentra el nombre '' dead_exchange '', entonces ese mensaje llegará a '' dead_exchange '' y lo entregará a '' dead queue '' ... Si aún tiene algún problema al respecto y si lo echo de menos entiende su problema ... . Escribe tu problema, seguramente lo revisaré ... Gracias ...
Nota: Debe publicar el mensaje en '' test_exchange '' porque ese enlace test_queue y test_exchange no tiene clave de enrutamiento y funcionará bien, pero si publica el mensaje en '' test_queue '' se usará la clave predeterminada de intercambio y enrutamiento. Luego de la expiración de los intentos de cola de mensajes para entregar ese mensaje muerto a dead_exchange con alguna clave de enrutamiento predeterminada y el mensaje no irá a esa cola.