使用AWS Lambda函数从SNS主题触发器读取和复制S3库存数据

时间:2019-01-30 01:38:38

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

我是一名数据分析师,并且是AWS lambda函数的新手。我有一个s3存储桶,用于存储来自数据仓库的库存数据,该数据是使用“ S3管理”选项卡下的“库存”功能生成的。

因此,可以说库存数据(报告)如下所示:

s3://my-bucket/allobjects/data/report-1.csv.gz
s3://my-bucket/allobjects/data/report-2.csv.gz
s3://my-bucket/allobjects/data/report-3.csv.gz

不管文件内容如何,​​我都有一个s3:// my-bucket / allobjects / data /的事件设置,它在GET或PUT之类的任何事件期间通知SNS主题。 (由于严格的管理,我无法更改此工作流程)

现在,我正尝试使用此SNS主题作为触发器来创建Lambda函数,并简单地将S3库存功能所生成的库存报告文件移至

s3://my-bucket/allobjects/data/ 

并按以下方式重新分区:

s3://my-object/allobjects/partitiondata/year=2019/month=01/day=29/report-1.csv.gz
s3://my-object/allobjects/partitiondata/year=2019/month=01/day=29/report-2.csv.gz
s3://my-object/allobjects/partitiondata/year=2019/month=01/day=29/report-3.csv.gz

如何使用lambda函数(可以使用node.js或python)读取SNS主题来实现此目的?任何帮助表示赞赏。

我尝试了一些类似的操作,这些操作是基于我在网上找到的一些smaple代码实现的,但没有帮助。

console.log('Loading function');

var AWS = require('aws-sdk');  
AWS.config.region = 'us-east-1';

exports.handler = function(event, context) {  
console.log("\n\nLoading handler\n\n");
var sns = new AWS.SNS();

sns.publish({
    Message: 'File(s) uploaded successfully',
    TopicArn: 'arn:aws:sns:_my_ARN'
}, function(err, data) {
    if (err) {
        console.log(err.stack);
        return;
    }
    console.log('push sent');
    console.log(data);
    context.done(null, 'Function Finished!');  
});
};

1 个答案:

答案 0 :(得分:2)

首选方法是让Amazon S3事件直接触发AWS Lambda函数。但是由于您无法更改此端口,因此流程如下:

  • Amazon S3事件将向Amazon SNS主题发送一条消息。
  • AWS Lambda函数已订阅SNS主题,因此它被触发并接收来自S3的消息。
  • Lambda函数提取出Bucket和Key,然后将S3调用copy_object()到另一个位置。 (没有 move 命令。您需要将对象复制到新的存储桶/密钥。)

event字段的内容类似于:

{
    "Records": [
        {
            "EventSource": "aws:sns",
            "EventVersion": "1.0",
            "EventSubscriptionArn": "...",
            "Sns": {
                "Type": "Notification",
                "MessageId": "1c3189f0-ffd3-53fb-b60b-dd3beeecf151",
                "TopicArn": "...",
                "Subject": "Amazon S3 Notification",
                "Message": "{\"Records\":[{\"eventVersion\":\"2.1\",\"eventSource\":\"aws:s3\",\"awsRegion\":\"ap-southeast-2\",\"eventTime\":\"2019-01-30T02:42:07.129Z\",\"eventName\":\"ObjectCreated:Put\",\"userIdentity\":{\"principalId\":\"AWS:AIDAIZCFQCOMZZZDASS6Q\"},\"requestParameters\":{\"sourceIPAddress\":\"54.1.1.1\"},\"responseElements\":{\"x-amz-request-id\":\"...",\"x-amz-id-2\":\"..."},\"s3\":{\"s3SchemaVersion\":\"1.0\",\"configurationId\":\"...\",\"bucket\":{\"name\":\"stack-lake\",\"ownerIdentity\":{\"principalId\":\"...\"},\"arn\":\"arn:aws:s3:::stack-lake\"},\"object\":{\"key\":\"index.html\",\"size\":4378,\"eTag\":\"...\",\"sequencer\":\"...\"}}}]}",
                "Timestamp": "2019-01-30T02:42:07.212Z",
                "SignatureVersion": "1",
                "Signature": "...",
                "SigningCertUrl": "...",
                "UnsubscribeUrl": "...",
                "MessageAttributes": {}
            }
        }
    ]
}

因此,需要从Message中提取上载对象的名称。

您可以使用如下代码:

import json

def lambda_handler(event, context):

    for record1 in event['Records']:
        message = json.loads(record1['Sns']['Message'])

        for record2 in message['Records']:

            bucket = record2['s3']['bucket']['name'])
            key = record2['s3']['object']['key'])

            # Do something here with bucket and key

    return {
        'statusCode': 200,
        'body': json.dumps(event)
    }