Nodejs sqs队列处理器

时间:2013-07-18 06:46:25

标签: 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 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吗?

2 个答案:

答案 0 :(得分:15)

首先,您应该定义使用亚马逊提供的长轮询技术,据我所知您已经在使用它,因为您在"WaitTimeSeconds": 20调用中有sqs.receiveMessage个参数。我希望你不要忘记在AWS Web interface中配置它。

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

<强>更新

至于我在新版本的代码中,有很多exec次调用。我认为最好将其最小化以使代码更清晰,更易于维护。但是,如果您离开,例如,在主readMessage()回调结束时只有一个调用,您将收到许多并行运行的PHP工作程序脚本 - 从它的角度来看,它可能并不是那么糟糕。性能 - 但您必须添加一些复杂的脚本来控制并行工作量。我认为你可以在receiveMessage回调中切断一些来电,尝试加入exec并加入主回调中的来电。

if

关于内存泄漏:我认为你不应该担心,因为"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()之后将值返回到父函数功能。

答案 1 :(得分:2)

如果您使用的是节点,请使用https://www.npmjs.com/package/sqs-worker模块。它会为你完成这项工作。

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