【问题标题】:I am learning to create AWS Lambdas. I want to create a "chain": S3 -> 4 Chained Lambda()'s -> RDS. I can't get the first lambda to call the second我正在学习创建 AWS Lambda。我想创建一个“链”:S3 -> 4 Chained Lambda()'s -> RDS。我无法让第一个 lambda 调用第二个
【发布时间】:2020-11-08 01:31:57
【问题描述】:

我真的什么都试过了。令人惊讶的是,谷歌在这方面没有太多答案。

当某个 .csv 文件上传到 S3 存储桶时,我想对其进行解析并将数据放入 RDS 数据库中。

我的目标是学习 lambda serverless 技术,这本质上是一个练习。因此,我过度设计了它。

事情是这样的:

  1. 上传 .csv 时 S3 触发 -> 调用 lambda(此部分完全有效)
  2. AAA_Thomas_DailyOverframeS3CsvToAnalytics_DownloadCsv 从 S3 下载 csv 并以文件的明文结束。然后应该将其传递给下一个 lambda。我试图做到这一点的方法是将第二个 lambda 作为目标。该函数有效,但第二个 lambda 从未被调用,我不知道为什么。
  3. AAA_Thomas_DailyOverframeS3CsvToAnalytics_ParseCsv 获取明文作为输入,并返回一个带有解析数据的 javascript 对象。
  4. AAA_Thomas_DailyOverframeS3CsvToAnalytics_DecryptRDSPass 仅连接到 KMS,获取加密的 RDS 密码,并将其与作为输入接收的数据一起传递给最后一个 lambda。
  5. AAA_Thomas_DailyOverframeS3CsvToAnalytics_PutDataInRds 然后最后将数据放入 RDS 中。

我创建了一个带有自定义子网、路由表、网关、对等连接等的自定义 VPC。我不知道这是否相关,但函数 2. 只能访问 s3 端点,3. 没有任何 Internet 访问,4. 是唯一可以正常访问 Internet(这是连接到 KSM 的唯一方法),5. 只能访问托管 RDS 的对等 VPC。


这是第一个 lambda 的代码:

// dependencies
const AWS = require('aws-sdk');
const util = require('util');
const s3 = new AWS.S3();
let region = process.env;


exports.handler = async (event, context, callback) =>
{
    var checkDates = process.env.CheckDates == "false" ? false : true;
    var ret = [];
    var checkFileDate = function(actualFileName)
    {
        if (!checkDates)
            return true;
            
        var d = new Date();
        var expectedFileName = 'Overframe_-_Analytics_by_Day_Device_' + d.getUTCFullYear() + '-' + (d.getUTCMonth().toString().length == 1 ? "0" + d.getUTCMonth() : d.getUTCMonth()) + '-' + (d.getUTCDate().toString().length == 1 ? "0" + d.getUTCDate() : d.getUTCDate());

        return expectedFileName == actualFileName.substr(0, expectedFileName.length);
    };

    for (var i = 0; i < event.Records.length; ++i)
    {
        var record = event.Records[i];
        
        try {
            if (record.s3.bucket.name != process.env.S3BucketName)
            {
                console.error('Unexpected notification, unknown bucket: ' + record.s3.bucket.name);
                continue;
            }
            
            if (!checkFileDate(record.s3.object.key))
            {
                console.error('Unexpected file, or date is not today\'s: ' + record.s3.object.key);
                continue;
            }

            const params = {
                Bucket: record.s3.bucket.name,
                Key: record.s3.object.key
            };
            var csvFile = await s3.getObject(params).promise();
            var allText = csvFile.Body.toString('utf-8');
            
            console.log('Loaded data:', {Bucket: params.Bucket, Filename: params.Key, Text: allText});
            
            ret.push(allText);
    
        } catch (error) {
            console.log("Couldn't download CSV from S3", error);
            return { statusCode: 500, body: error };
        }  
    }
    
    // I've been randomly trying different ways to return the data, none works. The data itself is correct , I checked with console.log()
    const response = {
        statusCode: 200,
        body: { "Records": ret }
    };
    
    return ret;
};

虽然这显示了 lambda 是如何设置的,尤其是它的目的地:

我已经 7 年没有在 Stackoverflow 上发过帖子了。这就是我的绝望。感谢您的帮助。

【问题讨论】:

  • 您是否查看过 CloudWatch Logs 以查看是否发布了任何错误消息?另外,您是通过在 S3 中创建对象还是通过单击“测试”按钮来测试该功能? (目的地不会通过测试按钮触发。)
  • @john cloudwatch 有一个奇怪的问题,当我从 lambda 页面链接打开它时,它说组日志不存在;如果我尝试创建它,我会收到一条错误消息,指出 aws/lambda/* 组名是为 lambdas 保留的。我正在使用测试按钮。这几乎肯定是问题所在。我确信它也会触发目的地,否则会很混乱(实际上我们在这里)。非常感谢。
  • 检查 lambda 权限是否可以写入日志,此外您还可以从监控部分查看最近的日志。
  • 确保与 Lambda 函数关联的 IAM 角色分配了 AWSLambdaBasicExecutionRole 策略,其中包括写入 CloudWatch Logs 的权限。
  • @John 我的返回函数正确吗?我返回什么重要吗?

标签: amazon-web-services amazon-s3 aws-lambda serverless


【解决方案1】:

与其让每个 Lambda 调用下一个,不如看看 AWS 状态机托管服务,step functions 可以为您处理这个工作流程。

通过提供input and outputs,您可以将输出传递给下一个函数,并在其中内置重试逻辑。

如果您没有太多经验,AWS 有一个 tutorial 通过链接 Lambda 设置步进函数。

通过使用它,您也无需考虑 Lambda 超时等配置问题。此外,它使您的代码更加模块化,从而改进了对单个功能的测试,同时也隔离了问题。

【讨论】:

  • 非常感谢。我一定会检查并试一试,因为正如我所说,我对一些“通用学习”更感兴趣,而不是在数据库中获取 csv。我有很多 AWS 经验,但没有 lambda 和相关技术。我主要处理ec2、s3和vpc的。这就是为什么为此设置的 vpc 非常疯狂?
  • 没问题,我相信它非常适合您的需求,因为您可以独立管理每个 Lambda。 Serverless 很棒,希望你喜欢 :)
  • 我仍在研究步进函数,特别是目前我正在努力处理来自 Node.js lambdas 的异步回调,但状态机(步进函数)绝对是要走的路,所以我接受了你的答案!
【解决方案2】:

目标包括其他 Lambda 函数的所有 Lambda 函数的执行角色必须在其附加的 IAM 策略之一中具有lambda:InvokeFunction IAM 权限。

这是来自Lambda documentation的sn-p:

要将事件发送到目的地,您的函数需要额外的权限。将具有所需权限的策略添加到函数的执行角色。每个目标服务需要不同的权限,如下所示:

  • Amazon SQS – sqs:SendMessage
  • Amazon SNS – sns:发布
  • Lambda – lambda:InvokeFunction
  • EventBridge – 事件:PutEvents

【讨论】:

  • 这不是我的问题,因为我根据文档确保它们是正确的(它们最初不是,但我很早就意识到了)。感谢您发布此内容,我相信这将对未来几年来自 google 的用户有所帮助
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-13
  • 2020-10-23
  • 1970-01-01
  • 2022-01-11
  • 2019-11-16
  • 2020-02-06
相关资源
最近更新 更多