带有aws-sdk的Amazon SQS receiveMessage Stall

时间:2016-05-09 08:53:30

标签: node.js amazon-web-services amazon-sqs

我正在使用aws-sdk节点模块(据我所知)批准的方式来轮询消息。

基本上总结为:

        sqs.receiveMessage({
            QueueUrl: queueUrl,
            MaxNumberOfMessages: 10,
            WaitTimeSeconds: 20
        }, function(err, data) {
            if (err) {
                logger.fatal('Error on Message Recieve');
                logger.fatal(err);
            } else {
                // all good
                if (undefined === data.Messages) {
                    logger.info('No Messages Object');
                } else if (data.Messages.length > 0) {
                    logger.info('Messages Count: ' + data.Messages.length);

                    var delete_batch = new Array();
                    for (var x=0;x<data.Messages.length;x++) {
                        // process
                        receiveMessage(data.Messages[x]);

                        // flag to delete

                        var pck = new Array();
                        pck['Id'] = data.Messages[x].MessageId;
                        pck['ReceiptHandle'] = data.Messages[x].ReceiptHandle;

                        delete_batch.push(pck);
                    }

                    if (delete_batch.length > 0) {
                        logger.info('Calling Delete');
                        sqs.deleteMessageBatch({
                            Entries: delete_batch,
                            QueueUrl: queueUrl
                        }, function(err, data) {
                            if (err) {
                                logger.fatal('Failed to delete messages');
                                logger.fatal(err);
                            } else {
                                logger.debug('Deleted recieved ok');
                            }
                        });
                    }
                } else {
                    logger.info('No Messages Count');
                }
            }
        });

receiveMessage是我的“如果我有足够的收集邮件就收集邮件的功能”功能

偶尔,我的脚本停滞不前,因为我根本没有获得对Amazon的响应,例如队列中没有消息要消耗,而不是点击WaitTimeSeconds并发送“no messages object”,不调用回调。

(我写的是亚马逊古怪)

我要问的是检测和处理此问题的最佳方法,因为我有一些代码可以停止对receiveMessage的并发调用。

这里建议的答案:Nodejs sqs queue processor还有防止并发消息请求查询的代码(授予它一次只获取一条消息)

我确实将整个事情包裹在

var running = false;
runMonitorJob = setInterval(function() {
    if (running) {
    } else {
        running = true;
        // call SQS.receive
    }
}, 500);

(在删除循环之后运行= false(不在它的回调中))

我的解决方案是

watchdogTimeout = setTimeout(function() {
    running = false;
}, 30000);

但是这肯定会留下一堆浮动的sqs.receive潜伏着,因而随着时间推移会有很多记忆?

(这项工作一直在运行,我让它在星期五运行,它在星期六早上停滞不前,直到我今天早上手动重新启动工作)

编辑:我已经看到它挂起约5分钟然后突然得到消息并且等待时间为20秒的情况它应该在20秒后抛出“无消息”。因此,约10分钟的WatchDog可能更实用(取决于业务逻辑的其余部分)

编辑:是长轮询已配置队列端。

编辑:这是aws-sdk的最新版本v2.3.9和NodeJS v4.4.4

2 个答案:

答案 0 :(得分:0)

我几天来一直在追逐这个(或类似的)问题,这是我注意到的:

  • 虽然仅在120秒后

  • ,但最终会返回receiveMessage调用
  • 对来自receiveMessage的并发调用由AWS.SDK库序列化,因此并行进行多次调用无效。

  • receiveMessage回调没有错误 - 实际上在120秒过后,它可能包含消息。

可以做些什么呢?这种事情可能由于多种原因而发生,并且这些事情中的一些/许多不一定能够被修复。答案是运行多个服务,每个服务调用receiveMessage并在消息到来时处理消息--SQS支持这一点。在任何时候,这些服务中的一个可能会达到120秒的延迟,但其他服务应该能够正常继续。

我特别的问题是我有一些关键的单件服务,无法承受120秒的停机时间。为此,我将研究1)使用HTTP而不是SQS将消息推送到我的服务中,或者2)在每个单例周围产生从属进程以从SQS获取消息并将它们推送到服务中。

答案 1 :(得分:0)

我也遇到了这个问题,但不是在调用receiveMessage而是sendMessage时遇到的。我还看到了恰好120秒的挂断。我还看到了Firehose等其他一些服务。

这使我转到AWS开发工具包中的这一行:

SQS Constructor

  

httpOptions:

     
      
  • timeout [Integer]-将套接字设置为在套接字闲置超时毫秒后超时。默认为两分钟(120000)。
  •   

要实施修复,我将SQS客户端的超时设置覆盖,该客户端在10秒后执行sendMessage超时,而另一个超时则需要25秒(我长时间轮询20秒):

var sendClient    = new AWS.SQS({httpOptions:{timeout:10*1000}});
var receiveClient = new AWS.SQS({httpOptions:{timeout:25*1000}});

我已经将这种产品投入生产了一个星期,我注意到我所有的SQS停滞问题都已消除。