RabbitMQ dead letter exchange никогда не получает сообщений

Я пытаюсь настроить свой первый обмен мертвыми письмами RabbitMQ, вот шаги, которые я использую через интерфейс веб-администратора:

  1. создать новый прямой обмен с именем " dead.письмо.тест"
  2. создать новую очередь " dead.письмо.очередь"
  3. Bind " мертвый.письмо.очередь " к " мертвым.письмо.тест"
  4. создайте новую очередь " test1 "с обменом мертвыми буквами, установленным на" dead.письмо.тест"
  5. Отправить сообщение в "test1"
  6. Nack (с requeue = false) сообщение в "test1"

Я ожидаю, что эти шаги должны поставить запись в " dead.письмо.очередь "через" мертвых.письмо.тест" обмен. Этого не происходит.

Я могу вручную поместить сообщение в " dead.письмо.тест" обмен и он появляется в "мертвых.письмо.очередь " так что я знаю, что это нормально.

когда я смотрю на пользовательский интерфейс администратора, он показывает, что параметр DLX настроен в очереди "test1".

где я ошибаюсь?

6 ответов


Gentilissimo Синьор был достаточно любезен, чтобы ответить на мой вопрос в Twitter. Проблема в том, что если ваш обмен мертвыми письмами настроен как прямой вы должны укажите ключ маршрутизации мертвых букв. Если вы просто хотите, чтобы все ваше взломанное сообщение отправилось в корзину мертвых писем для последующего расследования (как и я), тогда ваш обмен мертвыми письмами должен быть настроен как фанат.

вот обновленные шаги, которые работают:

  1. создать новый FANOUT обмен с названием " dead.письмо.тест"
  2. создать новую очередь " dead.письмо.очередь"
  3. Bind " мертвый.письмо.очередь " к " мертвым.письмо.тест"
  4. создайте новую очередь " test1 "с обменом мертвыми буквами, установленным на" dead.письмо.тест"
  5. Отправить сообщение в "test1"
  6. Nack (с requeue = false) сообщение в "test1"

обмен мертвыми письмами без ключа маршрутизации и с прямым обменом


Следуйте инструкциям, которые они будут работать наверняка: -
1. Создайте новую очередь с именем 'dead_queue'.
2. Создайте exchange с именем'dead_exchange' и тип обмена должен быть "прямой".
3. Bind 'dead_queue' и 'dead_exchange' без ключа маршрутизации.
4. Создать новую очередь с именем 'test_queue' и ее 'x-dead-letter-exchange 'name as'dead_exchange'
5. Создайте exchange с именем'test_exchange 'и тип обмена должен быть "прямым"
6. Bind 'test_exchange' и 'test_queue' без ключа маршрутизации.

и, наконец, мы проверим его. Для этого опубликуйте что-нибудь на 'test_exchange' С аргументом 'срок годности' установить на 10000. После это когда сообщение публикуется на 'test_exchange 'он пойдет в'test_queue 'и когда сообщение истекло с в очереди он будет искать параметр DLX (имя обмена мертвой буквы) там, что сообщение найти имя'dead_exchange ' тогда это сообщение достигнет 'dead_exchange' доставить 'мертвые очередь' .. Если у вас все еще есть какие-либо проблемы в этом отношении, и если я пропустил вашу проблему... напиши свою проблему я буду обязательно взгляните на него... Спасибо..

Примечание: необходимо опубликовать сообщение на 'test_exchange 'потому что эта привязка test_queue и test_exchange не имеет ключа маршрутизации, и она будет работать нормально, но если вы опубликуете сообщение на'test_queue ' будет использоваться ключ обмена и маршрутизации по умолчанию.Затем после истечения срока действия очереди сообщений пытается доставить это мертвое сообщение dead_exchange с некоторым ключом маршрутизации по умолчанию, и сообщение не будет идти к этому очередь.


если вы хотите использовать пользовательский ключ маршрутизации на dead letter exchange, вы должны установить x-dead-letter-routing-key при объявлении рабочей очереди (в вашем случае это test1), в противном случае будет использоваться ключ маршрутизации по умолчанию. В вашем случае RabbitMQ broker обнаруживает велоспорт и просто отбрасывает отклоненные сообщения.

что вам нужно, это иметь x-dead-letter-exchange=dead.letter.test и x-dead-letter-routing-key=dead.letter.queue аргументы на test1 очереди.


создать новый прямой обмен с именем " dead.письмо.тест"

правильно

создать новую очередь " dead.письмо.очередь"

правильно

Bind " мертвый.письмо.очередь " к " мертвым.письмо.тест"

правильно

создайте новую очередь " test1 "с обменом мертвыми буквами, установленным на" dead.письмо.тест"

Я предполагаю, что вы создаете test1 очередь и привязка к мертвым.письмо.тестовый обмен

Отправить сообщение в "test1"

Если вы хотите, чтобы ваше сообщение было получено мертвых.письмо.очередь вам придется предоставить ключ маршрутизации при отправке сообщения и клиентов, потребляющих мертвых.письмо.очередь также должна использовать тот же ключ маршрутизации

Если вы публикуете без ключа маршрутизации, только клиенты, подписанные на test1, получат сообщение.

Если вы публикуете сообщение прямой.письмо.проверьте exchange, после чего вся очередь получит сообщение. Он будет работать как обмен fanout

Итак, если вы хотите мертвы.письмо.очередь для получения сообщения вам придется опубликовать сообщение в этой очереди или использовать один и тот же ключ маршрутизации при публикации, подписке и публикации сообщения в exchange


Если вы хотите, чтобы все ваши очереди имели одинаковый обмен мертвыми письмами, проще установить общую политику:

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

Не нужно создавать fanout exchange, если это не обязательно.

вы можете создать прямой обмен, используя тот же ключ маршрутизации,который вы уже использовали для другого обмена. А также не нужно создавать новую очередь для нового обмена. Существующие очереди можно использовать с новым exchange. Вам просто нужно связать этот новый обмен с очередью.

вот мой прием.файл 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 });
    });
  });
});