sqs.recieveMessage即使在队列

时间:2018-02-28 14:10:08

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

所以我有3个lambdas,其中一个带有一个API事件触发一个lambda,它可以拉下50,000个对象并将它们全部推送到一个队列。

第二个lambda从队列中读取,一次10个,循环30次 - 意思是它读取,做东西,调用第三个lambda,返回promise,然后再次读取 - 30次,总共300次读取lambda执行的时间

第3个lambda从队列中获取信息并用它命中另一个端点。

问题在于第二个lambda ...首先我调用一个返回队列中消息数的函数,如果它大于零,我会读取它们。但是,即使队列中有20,000条消息,它也常常没有任何消息。我不确定为什么。

我将WaitTimeSeconds设置为20以进行长轮询。任何帮助将不胜感激,文档声称我可以通过FIFO队列读取高达3,000 /秒的速度,并且我无法获得接近该性能的任何地方。

以下是代码:

exports.handler = (event, context, callback) => {
  const sqs = new AWS.SQS({ region: process.env.AWS_REGION });
  getMessageCount(sqs)
    .then((messageCount) => {
      if (messageCount > 0) {
        mapSeries(range(0, 30), getMessages(sqs))
          .then((messageRes) => {
            callback(null, messageRes);
          })
          .catch(e => Promise.reject(e));
      }
      callback(null, 'No more messages');
    })
    .catch((e) => {
      callback(e);
    });
};

getMessageCount调用sqs.getQueueAttributes并返回接收消息数量的承诺。

mapSeries允许循环在迭代之前等待先前的promise被解析/拒绝,并且在每次迭代时它调用调用sqs.receiveMessage的getMessages并用数据调用第3个lambda。

对此表示赞赏,谢谢!

2 个答案:

答案 0 :(得分:0)

我理解你的问题,问题在于获取队列中的消息数量。如果您还提供了getMessageCount(sqs),我们可以确定您尝试从SQS检索的属性类型。

有三种类型的属性相关,以便在SQS中获取消息计数。这些属性如下所示。

  

ApproximateNumberOfMessages - 返回可见的近似数字   队列中的消息

     

ApproximateNumberOfMessagesNotVisible - 返回尚未超时但未删除的大致邮件数。

如果要包含等待添加的消息,您也可以考虑以下属性。

  

ApproximateNumberOfMessagesDelayed - 返回近似数字   等待添加到队列的消息。

通过考虑这些属性,您可以从SQS获得更准确的计数。

另外,如果我建议,我实现了一个类似的系统,但没有查找计数。我通过轮询一次检索10条消息,处理它们并从队列中删除它们。根据您的示例,您可以重复此操作30次。但是如果getMessages(sqs)函数返回一个空集,我们可以假设该列表为空。 (这取决于您使用的是短轮询还是长轮询)。然而,检查每一步的消息数似乎是多余的。这是根据这个例子,但它可能会根据用例推迟。

答案 1 :(得分:0)

通读API文档:https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/SQS.html#receiveMessage-property

参数:

MaxNumberOfMessages-(整数)

  

要返回的最大消息数。 Amazon SQS永不退货   超过此值的消息更多(但是,可能是更少的消息   回到)。有效值为1到10。默认值为1。

将您的代码包装在while循环中,因为0 小于1到10,所以通常会出现0条消息。

类似...

var messages = [];
while(messages.length < NUMBER_OF_MSGS_YOU_REALLY_WANT) {

    var new_messages = await getSQSMessages(NUMBER_OF_MSGS_YOU_REALLY_WANT - messages.length);
    if(new_messages.Data.Messages.length > 0) { 
       messages.push(new_messages.Data.Messages);
    }
}