【发布时间】:2020-11-08 01:31:57
【问题描述】:
我真的什么都试过了。令人惊讶的是,谷歌在这方面没有太多答案。
当某个 .csv 文件上传到 S3 存储桶时,我想对其进行解析并将数据放入 RDS 数据库中。
我的目标是学习 lambda serverless 技术,这本质上是一个练习。因此,我过度设计了它。
事情是这样的:
- 上传 .csv 时 S3 触发 -> 调用 lambda(此部分完全有效)
-
AAA_Thomas_DailyOverframeS3CsvToAnalytics_DownloadCsv从 S3 下载 csv 并以文件的明文结束。然后应该将其传递给下一个 lambda。我试图做到这一点的方法是将第二个 lambda 作为目标。该函数有效,但第二个 lambda 从未被调用,我不知道为什么。 -
AAA_Thomas_DailyOverframeS3CsvToAnalytics_ParseCsv获取明文作为输入,并返回一个带有解析数据的 javascript 对象。 -
AAA_Thomas_DailyOverframeS3CsvToAnalytics_DecryptRDSPass仅连接到 KMS,获取加密的 RDS 密码,并将其与作为输入接收的数据一起传递给最后一个 lambda。 -
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