NodeJS和RabbitMQ,如何确保处理我的邮件

时间:2018-01-21 15:09:50

标签: node.js rabbitmq

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

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

  1. 连接RabbitMQ
  2. 收听symfony_messages队列
  3. 如果product.created标识的邮件进入,则脚本使用spawn中的child_process执行特定命令。
  4. 我的问题是:有时候,我会重新开始"我的剧本如何确保在重新启动脚本时不处理事件?如何确保流程不会消耗消息并在产生流程之前停止?

    我想到的可能解决方案是:

    • 向nodeJS进程发送信号告诉他"处理最后一条消息并停止"。 但我怎样才能发送这样的信号

    以下是代码(如果您已经提出问题则不需要阅读):

    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});
        })
    })
    

1 个答案:

答案 0 :(得分:2)

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

同样,您可以使用Nack函数故意告诉RabbitMQ消息未被处理,我通常在进程函数错误处理程序(或promise.catch)中执行此操作。

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