Node.js Nodejs-sqs队列处理器

Node.js Nodejs-sqs队列处理器,node.js,amazon-sqs,Node.js,Amazon Sqs,我正在尝试编写一个nodejs sqs队列处理器 "use strict"; var appConf = require('./config/appConf'); var AWS = require('aws-sdk'); AWS.config.loadFromPath('./config/aws_config.json'); var sqs = new AWS.SQS(); var exec = require('child_process').exec; function readMessa

我正在尝试编写一个nodejs sqs队列处理器

"use strict";
var appConf = require('./config/appConf');
var AWS = require('aws-sdk');
AWS.config.loadFromPath('./config/aws_config.json');
var sqs = new AWS.SQS();
var exec = require('child_process').exec;
function readMessage() {
  sqs.receiveMessage({
    "QueueUrl": appConf.sqs_distribution_url,
    "MaxNumberOfMessages": 1,
    "VisibilityTimeout": 30,
    "WaitTimeSeconds": 20
  }, function (err, data) {
    var sqs_message_body;
    if (data.Messages) {
      if (typeof data.Messages[0] !== 'undefined' && typeof data.Messages[0].Body !== 'undefined') {
        //sqs msg body
        sqs_message_body = JSON.parse(data.Messages[0].Body);
        //make call to nodejs handler in codeigniter
        exec('php '+ appConf.CI_FC_PATH +'/index.php nodejs_handler make_contentq_call "'+ sqs_message_body.contentq_cat_id+'" "'+sqs_message_body.cnhq_cat_id+'" "'+sqs_message_body.network_id+'"',
          function (error, stdout, stderr) {
            if (error) {
              throw error;
            }
            console.log('stdout: ' + stdout);
            if(stdout == 'Success'){
              //delete message from queue
              sqs.deleteMessage({
                "QueueUrl" : appConf.sqs_distribution_url,
                "ReceiptHandle" :data.Messages[0].ReceiptHandle
              });
            }
          });
      }
    }
  });
}
readMessage();

对于队列中的单个消息,上述代码可以正常工作。我应该如何编写此脚本,以便它在处理所有消息之前一直轮询队列中的消息?我应该使用set timeout吗?

首先,您应该明确使用亚马逊提供的长轮询技术,据我所知,您已经在使用它了,因为您在
sqs.receiveMessage
调用中有
“WaitTimeSeconds”:20
参数。我希望您没有忘记在中配置它

关于消息轮询-您可以使用不同的技术,包括计时器,但我认为最简单的方法是在
receiveMessage
的回调函数末尾调用
readMessage()
函数。因此,队列中的下一条消息的处理(或等待)将在队列中的上一条消息的处理结束后立即开始

更新:

至于我,在你新版本的代码中,有很多
readMessage()
调用。我认为最好将其最小化,以使代码更清晰、更易于维护。但是,如果您离开,例如,在主
receiveMessage
回调末尾的唯一一个调用,您将收到大量并行运行的PHP工作程序脚本——从性能角度来看,这可能不是很糟糕——但您必须添加一些复杂的脚本来控制并行工作程序的数量。我认为您可以在
exec
callback中剪切一些调用,尝试加入
if
s并加入主回调中的调用

"use strict";
var appConf = require('./config/appConf');
var AWS = require('aws-sdk');
AWS.config.loadFromPath('./config/aws_config.json');
var delay = 20 * 1000;
var sqs = new AWS.SQS();
var exec = require('child_process').exec;
function readMessage() {
  sqs.receiveMessage({
    "QueueUrl": appConf.sqs_distribution_url,
    "MaxNumberOfMessages": 1,
    "VisibilityTimeout": 30,
    "WaitTimeSeconds": 20
  }, function (err, data) {
    var sqs_message_body;
    if (data.Messages) 
      && (typeof data.Messages[0] !== 'undefined' && typeof data.Messages[0].Body !== 'undefined')) {
        //sqs msg body
        sqs_message_body = JSON.parse(data.Messages[0].Body);
        //make call to nodejs handler in codeigniter
        exec('php '+ appConf.CI_FC_PATH +'/index.php nodejs_handler make_contentq_call "'+ sqs_message_body.contentq_cat_id+'" "'+sqs_message_body.cnhq_cat_id+'" "'+sqs_message_body.network_id+'"',
          function (error, stdout, stderr) {
            if (error) {
              // error handling 
            }
            if(stdout == 'Success'){
              //delete message from queue
              sqs.deleteMessage({
                "QueueUrl" : appConf.sqs_distribution_url,
                "ReceiptHandle" :data.Messages[0].ReceiptHandle
              }, function(err, data){                
              });
            }
            readMessage();                
          });
      }          
    }        
    readMessage();        
  });
}
readMessage();

关于内存泄漏:我认为您不必担心,因为下一次调用
readMessage()
发生在回调函数中,所以不是递归调用,递归调用的函数在调用
receiveMessage()
函数之后将值返回给父函数

如果您使用的是节点,请使用模块。它会帮你完成任务的

var SQSWorker = require('sqs-worker')

var options =
 { url: 'https://sqs.eu-west-1.amazonaws.com/001123456789/my-queue'
}

var queue = new SQSWorker(options, worker)

function worker(notifi, done) {
  var message;
  try {
    message = JSON.parse(notifi.Data)
  } catch (err) {
    throw err
  }

   // Do something with `message` 

   var success = true

   // Call `done` when you are done processing a message. 
   // If everything went successfully and you don't want to see it any more, 
   // set the second parameter to `true`. 
   done(null, success)
}

您好,请复习我的这个要点。在运行这个脚本的时候,我还应该担心内存泄漏吗?这是一篇老文章,但是你有没有遇到内存泄漏的问题,因为我对蓝鸟的承诺使用了几乎相同的想法。在每次投票中,我都能看到堆的总容量增加了约200kb。我认为这种方法仍然会泄漏内存。@napalm请添加更多细节,这将有助于解释为什么投票失败?也是一种选择