Node.js NodeJS和RabbitMQ,如何确保处理我的消息

Node.js NodeJS和RabbitMQ,如何确保处理我的消息,node.js,rabbitmq,Node.js,Rabbitmq,我正在构建一种微服务应用程序,并使用RabbitMQ在我的服务之间进行通信 我有一个nodeJS应用程序,它应该从RabbitMQ接收消息,并在收到特定消息时执行命令。下面是以下代码的作用: 连接到RabbitMQ 侦听symfony\u消息queue 如果出现由product.created标识的消息,脚本将使用child\u进程中的spawn执行特定命令 我的问题是:有时候,我要“重启”我的脚本。如何确保在重新启动脚本时不在处理事件的中间?如何确保进程不会消耗消息并在生成进程之前停止? 我想

我正在构建一种微服务应用程序,并使用RabbitMQ在我的服务之间进行通信

我有一个nodeJS应用程序,它应该从RabbitMQ接收消息,并在收到特定消息时执行命令。下面是以下代码的作用:

  • 连接到RabbitMQ
  • 侦听
    symfony\u消息
    queue
  • 如果出现由
    product.created
    标识的消息,脚本将使用
    child\u进程中的
    spawn
    执行特定命令
  • 我的问题是:有时候,我要“重启”我的脚本。如何确保在重新启动脚本时不在处理事件的中间?如何确保进程不会消耗消息并在生成进程之前停止?

    我想到的可能解决办法是:

    • 向nodeJS进程发送一个信号,告诉他“处理最后一条消息并停止”。但我怎么能发出这样的信号呢
    下面是代码(如果您已经得到问题,则无需阅读):


    消息处理成功后,在消息上使用channel.ack(消息)函数不是一种好模式吗?您已将noAck选项设置为true,但可以使用ACK机制确保消息只有在成功处理后才从队列中删除

    同样,您可以使用Nack函数故意告诉RabbitMQ消息未被处理,我通常在流程函数error handler(或promise.catch)中这样做


    我在将消息写入数据库的服务中使用了类似的机制。我只在消息写入数据库后确认消息。在RabbitMQ中设置死信交换/队列也很有用,这样任何被Nacked的消息都会在那里结束。然后,您可以检查这些消息,看看为什么它们不能被处理(或者在导致问题的错误条件得到解决后自动尝试重新处理)。

    消息处理成功后,对消息使用channel.ack(消息)功能不是一个好模式吗?您已将noAck选项设置为true,但可以使用ACK机制确保消息只有在成功处理后才从队列中删除

    同样,您可以使用Nack函数故意告诉RabbitMQ消息未被处理,我通常在流程函数error handler(或promise.catch)中这样做


    我在将消息写入数据库的服务中使用了类似的机制。我只在消息写入数据库后确认消息。在RabbitMQ中设置死信交换/队列也很有用,这样任何被Nacked的消息都会在那里结束。然后,您可以检查这些消息,看看为什么无法处理它们(或者在导致问题的错误条件解决后自动尝试重新处理)。

    太好了,我刚刚阅读了有关Ack和Nack功能的文档,它完全符合我的需要,谢谢!很酷,还可以查看死信功能,捕捉无法处理的奇怪消息非常有用。你点击一条消息,它就会进入死信队列。您的过程可以继续进行,并且您可以在以后更新您的算法来处理这些消息。您可以给我们一个代码示例吗?当消费者发送Nack时,我无法在发布方处理它…太好了,我只是阅读了关于Ack和Nack功能的文档,它完全符合我的需要,谢谢!很酷,还可以查看死信功能,捕捉无法处理的奇怪消息非常有用。你点击一条消息,它就会进入死信队列。您的过程可以继续进行,并且您可以在以后更新您的算法来处理这些消息。您可以给我们一个代码示例吗?当消费者发送Nack时,我无法在发布服务器端处理它。。。
    const amqp = require('amqplib/callback_api')
    const { spawn } = require('child_process')
    
    amqp.connect('amqp://guest:guest@127.0.0.1:5672', (err, conn) => {
    
        if (err) {
            console.log(err)
            return
        }
    
        conn.createChannel((err, channel) => {
            let q = 'symfony_messages'
    
            channel.assertQueue(q, {
                durable: false
            })
    
            console.log(" [*] Waiting for messages in %s. To exit press CTRL+C", q);
    
            channel.consume(q, (msg) => {
                let event = JSON.parse(msg.content.toString())
    
                if (event.name === 'product.created') {
                    console.log('Indexing order...')
    
                    let cp = spawn('php', [path.join(__dirname, '..', '..', 'bin', 'console'), 'elastic:index:orders', event.payload.product_id])
    
                    cp.stdout.on('data', (data) => {
                        console.log(`stdout: ${data}`);
                    })
    
                    cp.stderr.on('data', (data) => {
                        console.log(`stderr: ${data}`);
                    })
    
                    cp.on('close', (code) => {
                        console.log(`child process exited with code ${code}`);
                    })
                }
    
            }, {noAck: true});
        })
    })