RabbitMQ死信交换从不获取消息

RabbitMQ死信交换从不获取消息,rabbitmq,dead-letter,Rabbitmq,Dead Letter,我正在尝试设置我的第一个RabbitMQ死信交换,以下是我通过web管理界面使用的步骤: 创建名为“dead.letter.test”的新直接交换 创建新队列“dead.letter.queue” 将“dead.letter.queue”绑定到“dead.letter.test” 创建新队列“test1”,死信交换设置为“dead.letter.test” 将消息发送到“test1” Nack(REQUUE=false)在“test1”中显示消息 我希望这些步骤应该通过“dead.letter.

我正在尝试设置我的第一个RabbitMQ死信交换,以下是我通过web管理界面使用的步骤:

  • 创建名为“dead.letter.test”的新直接交换
  • 创建新队列“dead.letter.queue”
  • 将“dead.letter.queue”绑定到“dead.letter.test”
  • 创建新队列“test1”,死信交换设置为“dead.letter.test”
  • 将消息发送到“test1”
  • Nack(REQUUE=false)在“test1”中显示消息
  • 我希望这些步骤应该通过“dead.letter.test”交换将记录放入“dead.letter.queue”中。这并没有发生

    我可以手动将一条消息放入“dead.letter.test”交换,它会显示在“dead.letter.queue”中,所以我知道这是可以的

    当我查看管理UI时,它显示DLX参数是在队列“test1”上设置的

    我哪里做错了

    创建名为“dead.letter.test”的新直接交换

    正确的

    创建新队列“dead.letter.queue”

    正确的

    将“dead.letter.queue”绑定到“dead.letter.test”

    正确的

    创建新队列“test1”,死信交换设置为“dead.letter.test”

    我假设您正在创建test1队列并将其绑定到dead.letter.test交换

    将消息发送到“test1”

    如果您希望dead.letter.queue接收您的邮件,则在发送邮件时必须提供路由密钥,而使用dead.letter.queue的客户端也应使用相同的路由密钥

    如果您在没有路由密钥的情况下发布,则只有订阅了test1的客户端才会收到消息

    如果将消息发布到direct.letter.test exchange,则所有队列都将接收该消息。它将像扇出交换一样工作


    所以,如果您希望dead.letter.queue接收邮件,则必须在该队列中发布邮件,或者在发布和订阅邮件以及将邮件发布到exchange时必须使用相同的路由密钥

    如果您希望在dead-letter exchange上使用自定义路由密钥,则在声明工作时必须设置
    x-dead-letter-routing-key
    队列(在您的情况下是
    test1
    ),否则将使用默认路由密钥。在您的情况下,RabbitMQ代理检测循环并简单地丢弃被拒绝的消息


    您需要的是在
    test1
    队列上设置
    x-dead-letter-exchange=dead.letter.test
    x-dead-letter-routing-key=dead.letter.queue
    参数。

    Gentilisimo Signore很乐意在Twitter上回答我的问题。问题是,如果死信交换设置为DIRECT,则必须指定死信路由密钥。如果你只是想把你所有的NACKed消息放入一个死信桶,以便以后进行调查(就像我一样),那么你的死信交换应该设置为扇出

    以下是有效的更新步骤:

  • 创建名为“dead.letter.test”的新扇出
  • 创建新队列“dead.letter.queue”
  • 将“dead.letter.queue”绑定到“dead.letter.test”
  • 创建新队列“test1”,死信交换设置为“dead.letter.test”
  • 将消息发送到“test1”
  • Nack(REQUUE=false)在“test1”中显示消息
  • 无路由密钥和直接交换的死信交换
    请按照这些步骤操作,这些步骤肯定会起作用:-
    1.创建一个名为“dead_queue”的新队列
    2.创建名为“死交换”的交换,交换类型应为“直接交换”。
    3.不使用路由密钥绑定“死队列”和“死交换”。
    4.创建一个名为“test\u queue”的新队列,并将其“x-dead-letter-exchange”名称设置为“dead\u exchange”
    5.创建名为“test_exchange”的交换,交换类型应为“direct”
    6.不使用路由密钥绑定“测试交换”和“测试队列”

    最后我们会检查它。为此,在参数“expiration”设置为10000的“test_exchange”上发布某些内容。在此之后,当消息在“test_exchange”上发布时,它将转到“test_queue”,当消息在队列中过期时,它将在队列中查找DLX参数(死信交换名称),该消息将在此处找到名称“Dead_exchange”,然后该消息将到达“Dead_exchange”并将其传递到“Dead queue”。。 如果你仍然对此有任何问题,如果我不理解你的问题。。。写下你的问题,我一定会仔细考虑的。。。谢谢


    注意:必须在“test_exchange”上发布消息,因为该test_队列和test_exchange绑定没有路由密钥,可以正常工作,但如果在“test_队列”上发布消息,则将使用默认的exchange和路由密钥。然后,在消息队列过期后,尝试使用某些默认密钥将该死消息传递到死_exchange路由密钥和消息不会进入该队列。

    如果希望所有队列都具有相同的死信交换,则更容易设置常规策略:

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

    如果不是强制的,则不需要创建扇出交换

    您可以使用已用于其他exchange的相同路由密钥创建直接exchange。而且也不需要为新的exchange创建新队列。您可以将现有队列与新exchange一起使用。您只需要将新的exchange与队列绑定

    这是我的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 });
        });
      });
    });
    
    var-amqp=require(“amqplib/callback_-api”);
    var crontab=require('node-crontab');
    amqp.connect(“amqp://localhost,功能(错误,连接){
    conn.createChannel(函数(错误,通道){
    var ex=‘直接_日志’;
    var ex2=‘死信测试’;
    风险值严重性='enterprise-1-key';
    //断言“直接”交换
    ch.assertExchange(例如,'direct',{持久:true});
    //断言“死信测试”交换
    ch.assertExchange(ex2,'direct',{dustable:true});
    //如果确认为nack(),则消息将存储在第二个交换机中,即ex2
    
    ackMode="MANUAL"
    
    spring.rabbitmq.listener.simple.default-requeue-rejected=false
    spring.rabbitmq.listener.simple.concurrency=5
    spring.rabbitmq.listener.simple.max-concurrency=10