首页 > 解决方案 > 为什么我的 Lambda 函数一次调用会发送两次 SQS 消息?

问题描述

我只需要一次调用一次将消息传递到标准(不是 FIFO,但与问题无关)SQS 队列。

但是,下面的代码通过 1 个呼叫发送 2 条消息。

const AWS = require('aws-sdk')
AWS.config.update({region: process.env.AWS_REGION})
const sqs = new AWS.SQS({apiVersion: '2012-11-05'});

async function sendToSQSEvent(body,attributes=null){
    var m_body 
    if (attributes != null)
    {
            m_body = {
                body : body,
                attributes : attributes
                };
    }
    else{
        m_body = body;
    }
    m_body = JSON.stringify(m_body);
            
 var params = {
    //  DelaySeconds: 0,   <-- i try but only delay reception 
      MessageAttributes: {
        "Title": {
          DataType: "String",
          StringValue: "TIME_OUT"
        },
        "Author": {
          DataType: "String",
          StringValue: "LAMBDA_IN"
        },
      },
      MessageBody: m_body,
      QueueUrl: "https://my_url/sqs"
    };
    console.log('_________CALL_______________');
    var r = await sqs.sendMessage(params, function(err, data) {
      if (err) {
        console.log("Error", err);
      } else {
        console.log("Success", data.MessageId ,data);
      }
    }).promise(console.log("_________in promise___________"));
   console.log("___end")
}

exports.handler = async (event, context) => {
     await sendToSQSEvent(event)
};

控制台输出为:

START RequestId: RequestId Version: $LATEST
2021-10-11T06:23:52.992Z    RequestId   INFO    _________CALL_______________
2021-10-11T06:23:53.425Z    RequestId   INFO    _________in promise___________
2021-10-11T06:23:53.728Z    RequestId   INFO    Success ********-****-****-****-*********b4f {
  ResponseMetadata: { RequestId: '********-****-****-****-*********89d' },
  MD5OfMessageBody: '********************************8f',
  MD5OfMessageAttributes: '***********************1b0',
  MessageId: '********-****-****-****-*********b4f'
}
2021-10-11T06:23:53.786Z    RequestId   INFO    ___end
2021-10-11T06:23:53.807Z    RequestId   INFO    Success ********-****-****-****-*********665 {
  ResponseMetadata: { RequestId: '********-****-****-****-********835' },
  MD5OfMessageBody: '***********************28f',
  MD5OfMessageAttributes: '***********************1b0',
  MessageId: '********-****-****-****-*********665'
}
END RequestId: RequestId

问题是什么?

标签: javascriptamazon-web-servicesaws-lambdaes6-promiseamazon-sqs

解决方案


当您将同步 回调( function(err, data)) 与异步 承诺( await, async function sendToSQSEvent(...)) 混合时,它会发送两次消息。

您可以看到这一点,因为 CloudWatch 正在记录 2 个sqs.sendMessage(...)响应。

我建议坚持后者。


这应该是您的 SQSsendMessage逻辑,它为您的处理程序返回一个承诺对象。

return sqs.sendMessage(params).promise();

然后,您可以检查处理程序中的响应:

exports.handler = async (event, context) => {
    try {
        var data = await sendToSQSEvent(event)
        console.log("Success", data.MessageId ,data);
    }
    catch (err){
        console.log("Error", err);
    }
};

这应该是最终的工作结果:

const AWS = require('aws-sdk')
AWS.config.update({
    region: process.env.AWS_REGION
})
const sqs = new AWS.SQS({
    apiVersion: '2012-11-05'
});

async function sendToSQSEvent(body, attributes = null) {
    var m_body
    if (attributes != null) {
        m_body = {
            body: body,
            attributes: attributes
        };
    } else {
        m_body = body;
    }
    m_body = JSON.stringify(m_body);

    var params = {
        MessageAttributes: {
            "Title": {
                DataType: "String",
                StringValue: "TIME_OUT"
            },
            "Author": {
                DataType: "String",
                StringValue: "LAMBDA_IN"
            },
        },
        MessageBody: m_body,
        QueueUrl: "https://my_url/sqs"
    };

    return sqs.sendMessage(params).promise();
}

exports.handler = async (event, context) => {
    try {
        var data = await sendToSQSEvent(event)
        console.log("Success", data.MessageId ,data);
    }
    catch (err){
        console.log("Error", err);
    }
};

推荐阅读