首页 文章

AWS - 从Lambda / Node.js发送1000封电子邮件

提问于
浏览
0

我有一个由SNS触发的“主”Lambda函数 . 它从数据库中提取收件人列表,并且需要根据模板向每个收件人发送一条消息,替换诸如名字等内容 .

我设置它的方式是我创建了另一个名为“email-send”的Lambda函数,该函数订阅了“email-send”主题 . 然后,“main”Lambda循环通过收件人列表,并使用适当的有效负载(from,to,subject,message)将消息发布到“email-send” . 这可能最终需要在一个批次中处理1000个电子邮件 .

这是一个很好的方法来满足我的要求吗?也许Lambda / SNS不是一种可行的方式?如果是这样,你会推荐什么?

有了这个设置,当我的“main”函数完成运行时,我遇到问题,并且某种方式“sns.publish”在我的循环中没有被触发 . 我假设因为我没有让它完成 . 但我不知道如何修复它,成为一个循环 .

这是我的Lambda函数的片段:

exports.handler = (event, context, callback) => {
        // code is here to pull data into "data" array

        // process records
        for (var i = 0; i < data.length; i++) {
            var sns = new aws.SNS();
            sns.publish({
              Message: JSON.stringify({ from: data[i].from, to: data[i].to, subject: subject, body: body }),
              TopicArn: 'arn:aws:sns:us-west-2:XXXXXXXX:email-send'
            }, function(err, data) {
              if (err) {
                console.log(err.stack);
              } else {
                console.log('SNS pushed!');
              }
            });  
        }
        context.succeed("success");
};

谢谢你的帮助 .

2 回答

  • 0

    你的代码是这样做的......

    • Begin 调用 sns.publish() 1000次

    • 返回(通过 context.succeed()

    你没等等1000个电话完成!

    你的代码应该做的是......

    • Begin 调用 sns.publish() 1000次

    • sns.publish() 的所有调用都已返回时,则 return . ( context.succeed 已经过时了,所以我们应该使用 callback() 代替) .

    像这样......

    // Instantiate the client only once instead of data.length times
    const sns = new aws.SNS();
    
    exports.handler = (event, context, callback) => {
      const snsCalls = []
      for (var i = 0; i < data.length; i++) {
        snsCalls.push(sns.publish({
          Message: JSON.stringify({
            from: data[i].from,
            to: data[i].to,
            subject: subject,
            body: body
          }),
          TopicArn: 'arn:aws:sns:us-west-2:XXXXXXXX:email-send'
        }).promise();
      }
    
      return Promise.all(snsCalls)
        .then(() => callback(null, 'Success'))
        .catch(err => callback(err));
    };
    
  • 0

    我认为更好的方法是使用AWS Lambda API .

    这样,你就不需要SNS了 .

    For example:

    var lambda = new AWS.Lambda({region: AWS_REGION});
    function invokeWorkerLambda(task, callback) {
        var params = {
            FunctionName: WORKER_LAMBDA_NAME,
            InvocationType: 'Event',
            Payload: JSON.stringify({.....})
        };
        lambda.invoke(params, function(err, data) {
            if (err) {
                console.error(err, err.stack);
                callback(err);
            } else {
                callback(null, data);
            }
        });
    }
    

    如您所见,对于lambda函数的调用,您不需要SNS .

    Important: 另一个建议是创建一个调用数组( functions ),然后按如下方式执行它们:

    async.parallel(invocations, function(err) {
        if (err) {
            console.error(err, err.stack);
            callback(err);
        }
    });
    

    Take a look at this link where I got a lot of knowledge about Lambda invocation: https://cloudonaut.io/integrate-sqs-and-lambda-serverless-architecture-for-asynchronous-workloads/

    Hope it helps!

相关问题