【问题标题】:Manually invoke lambda with s3 event in java在 java 中使用 s3 事件手动调用 lambda
【发布时间】:2021-06-10 23:48:51
【问题描述】:

有一个实现的 lambda RequestHandler<S3Event, Void> 并有这样的处理程序Void handleRequest(S3Event event, Context context) {log.info(" Event => " + event)....}

S3Event 这里的类型是com.amazonaws.services.lambda.runtime.events.S3Event;

尝试手动调用 lambda 而不将任何数据上传到 s3。所以使用LambdaInvokerFactory创建lambda客户端和lambda接口为:

public interface Lambdas {

        @LambdaFunction(functionName = "Foo)
        Void bar(S3Event event);
    }

使用this 引用手动创建S3EventNotification.S3EventNotificationRecord ( of type com.amazonaws.services.lambda.runtime.events.S3EventNotification) 。创建后在本地记录S3Event 打印如下:

{
    "Records": [
        {
            "records": [
                {
                    "awsRegion": "us-west-2",
                    "eventName": "ObjectCreated:Put",
                    "eventSource": "aws:s3",
                    "eventTime": {
                        "era": 1,
                        "dayOfYear": 71,
                        "year": 2021,
                        "dayOfMonth": 12,
                        "dayOfWeek": 5,
                        "weekyear": 2021,
                        "weekOfWeekyear": 10,
                        "monthOfYear": 3,
                        "millisOfDay": 0,
                        "yearOfCentury": 21,
                        "centuryOfEra": 20,
                        "millisOfSecond": 0,
                        "yearOfEra": 2021,
                        "secondOfMinute": 0,
                        "secondOfDay": 0,
                        "minuteOfHour": 0,
                        "minuteOfDay": 0,
                        "hourOfDay": 0,
                        "millis": 1615536000000,
                        "zone": {
                            "fixed": false,
                            "uncachedZone": {
                                "fixed": false,
                                "cachable": true,
                                "id": "America/Los_Angeles"
                            },
                            "id": "America/Los_Angeles"
                        },
                        "chronology": {
                            "zone": {
                                "fixed": false,
                                "uncachedZone": {
                                    "fixed": false,
                                    "cachable": true,
                                    "id": "America/Los_Angeles"
                                },
                                "id": "America/Los_Angeles"
                            }
                        },
                        "afterNow": false,
                        "beforeNow": true,
                        "equalNow": false
                    },
                    "eventVersion": "2.0",
                    "requestParameters": {
                        "sourceIPAddress": "127.0.0.1"
                    },
                    "responseElements": {
                        "xAmzId2": "Foo",
                        "xAmzRequestId": "Bar"
                    },
                    "s3": {
                        "configurationId": "Foo",
                        "bucket": {
                            "name": "Foo",
                            "ownerIdentity": {
                                "principalId": "arn:aws:iam::Foo"
                            },
                            "arn": "arn:aws:s3::Foo"
                        },
                        "object": {
                            "key": "FooBar.txt",
                            "size": 10,
                            "eTag": "Foo",
                            "versionId": "Foo",
                            "sequencer": "Foo",
                            "urlDecodedKey": "FooBar.txt",
                            "sizeAsLong": 10
                        },
                        "s3SchemaVersion": "1.0"
                    },
                    "userIdentity": {
                        "principalId": "arn:aws:iam::Foo"
                    }
                }
            ]
        }
    ]
}

但是在调用 bar(S3Event) 时,它会调用 lambda 但日志显示它为空:

Event => {[]} 

我尝试过的事情

  • 将界面的输入改为Void bar(Map<String, Object> event) 并像这样调用 lambda bar(ImmutableMap.of("Records", event.getRecords()) 它调用 lambda 但出现以下错误:
An error occurred during JSON parsing: java.lang.RuntimeException
java.lang.RuntimeException: An error occurred during JSON parsing
Caused by: lambdainternal.util.ReflectUtil$ReflectException: java.lang.reflect.InvocationTargetException
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
Caused by: java.lang.IllegalArgumentException: Invalid format: "{"year":2021,"dayOfYear":71,"equ..."
    at org.joda.time.format.DateTimeFormatter.parseDateTime(Unknown Source)
    at org.joda.time.DateTime.parse(Unknown Source)
    at org.joda.time.DateTime.parse(Unknown Source)
    at com.amazonaws.services.s3.event.S3EventNotification$S3EventNotificationRecord.<init>(S3EventNotification.java:386)
    at com.amazonaws.services.s3.event.S3EventNotification$S3EventNotificationRecord.<init>(S3EventNotification.java:355)
    ... 4 more

这就是记录的创建方式:

return new S3EventNotification.S3EventNotificationRecord(
            region,
            EVENT_NAME,
            EVENT_SOURCE,
            DateTime.now().toString(),
            EVENT_VERSION,
            new S3EventNotification.RequestParametersEntity(SOURCE_IP_ADDRESS),
            new S3EventNotification.ResponseElementsEntity(
                RandomStringUtils.randomAlphanumeric(SIZE),
                RandomStringUtils.randomAlphanumeric(SIZE)
            ),
            s3Entity,
            getUserIdentityEntity(accountId)

不确定这里出了什么问题?

【问题讨论】:

  • 上传内容时有效吗?
  • 是的,当我将任何内容上传到 s3 存储桶时它会起作用,它会触发 lambda 并执行所需的操作。
  • 我不相信,我们需要两个数组,我们只需要一个 Records ,尝试摆脱 "records" 数组层!

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


【解决方案1】:

S3 事件源到 lambda 的格式记录在 here

它是一个包含 Records 数组的对象

所以,它应该在下面,我们不需要第二层 records 数组。

{
  "Records": [
    {
      "eventVersion": "2.1",
      "eventSource": "aws:s3",
      "awsRegion": "us-east-2",
      "eventTime": "2019-09-03T19:37:27.192Z",
      "eventName": "ObjectCreated:Put",
      "userIdentity": {
        "principalId": "AWS:AIDAINPONIXQXHT3IKHL2"
      },
      "requestParameters": {
        "sourceIPAddress": "205.255.255.255"
      },
      "responseElements": {
        "x-amz-request-id": "D82B88E5F771F645",
        "x-amz-id-2": "vlR7PnpV2Ce81l0PRw6jlUpck7Jo5ZsQjryTjKlc5aLWGVHPZLj5NeC6qMa0emYBDXOo6QBU0Wo="
      },
      "s3": {
        "s3SchemaVersion": "1.0",
        "configurationId": "828aa6fc-f7b5-4305-8584-487c791949c1",
        "bucket": {
          "name": "lambda-artifacts-deafc19498e3f2df",
          "ownerIdentity": {
            "principalId": "A3I5XTEXAMAI3E"
          },
          "arn": "arn:aws:s3:::lambda-artifacts-deafc19498e3f2df"
        },
        "object": {
          "key": "b21b84d653bb07b05b1e6b33684dc11b",
          "size": 1305107,
          "eTag": "b21b84d653bb07b05b1e6b33684dc11b",
          "sequencer": "0C0F6F405D6ED209E1"
        }
      }
    }
  ]
}

【讨论】:

  • 修复了records": [{...]},但是,eventTime 字段没有创建为 String ,它变成了 "eventTime": { "year": 2019,"dayOfMonth": 3, ... } 所以它失败了 Caused by: com.amazonaws.services.lambda.invoke.LambdaFunctionException: Invalid format: "{"year":2019,"dayOfYear":246,"eq..."
  • 您在尝试"eventTime": "2019-09-03T19:37:27.192Z" 时遇到错误?
  • 无法使用字符串值创建 eventTime。使用new S3EventNotification.S3EventNotificationRecord( ...) 时,它会生成eventTime 作为对象。
【解决方案2】:

这里有一些东西,

  1. 正如Balu Vyamajala 提到的以匹配记录格式。
  2. 使用3.5 作为依赖项,它创建了eventTime 字段作为对象,而不是在调用lambda 时抛出com.amazonaws.services.lambda.invoke.LambdaFunctionException: Invalid format: "{"year":2019,"dayOfYear":246,"eq... 的字符串。使用2.8 创建 eventTime:2019-09-03T19:37:27.192Z 解决了这个问题。

当前界面。

@LambdaFunction(functionName = Foo)
        Void Bar(S3Event payload);

但是,S3EventNotificationRecord 构造函数已被弃用。您可以在format 中创建json doc 并使用S3EventNotification.parseJson 获取记录。

【讨论】:

    猜你喜欢
    • 2020-01-03
    • 2017-05-05
    • 2020-03-25
    • 1970-01-01
    • 1970-01-01
    • 2010-10-19
    • 1970-01-01
    • 2011-04-19
    • 1970-01-01
    相关资源
    最近更新 更多