【问题标题】:AWS SNS publishing to a subscribed Lambda function logs null fieldsAWS SNS 发布到订阅的 Lambda 函数记录空字段
【发布时间】:2015-12-22 05:18:32
【问题描述】:

试图将其发布到 AWS 论坛,但无论这意味着什么,我的帐户似乎“尚未准备好”。

我设置了一个接受 POJO 的 AWS Lambda 函数(用 Java 编写),以便自动反序列化 JSON。我正在使用的测试 JSON 如下所示,它表示一旦一切启动并运行,将从消息的最终来源发送的 JSON 字符串。

{"sender":"Joe", "id":1, "event":"started", "ticks":2, "time":"20150623T214256Z", "version":"1.0"}

当我通过从 Lambda“测试”控制台发布到它来测试它时,这非常有效。

我现在尝试通过将 Lambda 函数订阅到主题来连接 SNS,并且我正在从 SNS 控制台对其进行测试。我尝试使用“原始数据”(未显示任何结果)和使用“JSON 生成器”数据选项生成的 JSON 发送与上述相同的消息,但我遇到了一个问题,当 SNS 出现时将消息发送到 Lambda 函数,POJO 被实例化,但要么调用默认构造函数,要么调用参数化构造函数并使用所有空值。无论哪种方式,当 Lambda 函数通过调用 POJO 中重写的 toString() 方法记录消息时,它会为所有变量打印出 null 而没有任何错误消息。同样,SNS 主题配置为登录到 Cloudwatch,它也没有报告任何错误。它获得 HTTP 状态 202。

这是新生成的 JSON 消息。

{
"default": "{\"sender\":\"Joe\", \"id\":1, \"event\":\"started\", \"ticks\":2, \"time\":\"20150623T214256Z\", \"version\":\"1.0\"}", 
"lambda": "{\"sender\":\"Joe\", \"id\":1, \"event\":\"started\", \"ticks\":2, \"time\":\"20150623T214256Z\", \"version\":\"1.0\"}", 
}

以下是日志消息。

Lambda 的日志:

START RequestId: 238a0546-627d-11e5-b228-817bf2a1219a    
Received the following :: We have the following Message{sender=null, id=null, event=null, ticks=null, time=null, version=null}    
END RequestId: 238a0546-627d-11e5-b228-817bf2a1219a   
REPORT RequestId: 238a0546-627d-11e5-b228-817bf2a1219a  Duration: 26.23 ms  Billed Duration: 100 ms     Memory Size: 1536 MB    Max Memory Used: 69 MB  

SNS 日志:

{ "status": "SUCCESS", "notification": { "timestamp": "2015-09-24 05:28:51.079", "topicArn": "arn:aws:sns:us-east-1:256842276575:App", "messageId": "3f5c0fa1-8a50-5ce3-b7c9-41dc060212c8", "messageMD5Sum": "65a5cb6d53616bd385f72177fe98ecc2" }, "delivery": { "statusCode": 202, "dwellTimeMs": 92, "attempts": 1, "providerResponse": "{\"lambdaRequestId\":\"238a0546-627d-11e5-b228-817bf2a1219a\"}", "destination": "arn:aws:lambda:us-east-1:256842276575:function:App-Lambda-Trigger" } }

以下是适用的 Lambda 函数代码:

package com.mycompany;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.LambdaLogger;

public class LambdaHandler {

    public void Handler(Message msg, Context context) {
        LambdaLogger logger = context.getLogger();
        logger.log("Received the following :: " + msg.toString());
    }
}

public class Message {
    private String sender;
    private Integer id;
    private String event;
    private Integer ticks;
    private String time;
    private Double version;

public Message(String sender, Integer id, String event, Integer ticks, String time, Double version) {
    this.sender = sender;
    this.id = id;
    this.event = event;
    this.ticks = ticks;
    this.time = time;
    this.version = version;
}

... getters/setters ...

public Message() {
}   

@Override
public String toString() {
    return "We have the following Message{" + "sender=" + getSender() + ", id=" + id + ", event=" + event + ", ticks=" + ticks + ", time=" + time + ", version=" + version + '}';
}

在进行了一些挖掘并查看了一些 javascript 示例(我似乎找不到任何订阅 SNS 的函数的 Java 示例)之后,似乎它们都收到了“事件”。我在 AWS 的 Github 存储库中找到了一个 Java 类 SNSEvent (https://github.com/aws/aws-lambda-java-libs/blob/master/aws-lambda-java-events/src/main/java/com/amazonaws/services/lambda/runtime/events/SNSEvent.java),但它不在官方 Javadoc 中。我无法找到任何 AWS 文档来记录 Java Lambda 函数设置以接收反序列化的 POJO(我不敢相信这并不常见),而且我找不到任何指定发送的对象类型的任何内容Lambda 函数的 SNS 主题,如果事实上我不应该期望 POJO 类型。

有人可以澄清一下,我的 Lambda 函数应该接收什么类型的对象?有人可以提供一些示例代码吗?

任何帮助将不胜感激。

编辑 1

根据建议,我修改了我的函数以接受 SNSEvent 和 Context 对象,但我的函数抛出了以下异常:

Error loading method handler on class com.app.LambdaHandler: class java.lang.NoClassDefFoundError java.lang.NoClassDefFoundError: com/amazonaws/services/lambda/runtime/events/SNSEvent 
at java.lang.Class.getDeclaredMethods0(Native Method) 
at java.lang.Class.privateGetDeclaredMethods(Class.java:2701) 
at java.lang.Class.privateGetPublicMethods(Class.java:2902) 
at java.lang.Class.getMethods(Class.java:1615) Caused by: java.lang.ClassNotFoundException: com.amazonaws.services.lambda.runtime.events.SNSEvent 
at java.net.URLClassLoader.findClass(URLClassLoader.java:381) 
at java.lang.ClassLoader.loadClass(ClassLoader.java:424) 
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)

好像运行环境不识别SNSEvent?

【问题讨论】:

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


    【解决方案1】:

    我认为你应该改变两件事:

    1. 您的 Message 类不遵循 Lambda 将用于反序列化事件对象的 getX/setX 访问器的预期 Lambda POJO format
    2. 如果您的事件来自 SNS,它将遵循通用 SNS 对象格式而不是您的自定义格式。您必须检查 SNS 事件以提取 Message 中的自定义数据,然后单独解析。在 Lambda 中的 Actions > Configure sample event 下查看 SNS 事件模板。

    这是一个示例 Lambda 函数,用于在 Java 中处理 SNS 事件,使用 AWS Lambda Java Support Libraries

    package example;
    
    import com.amazonaws.services.lambda.runtime.Context;
    import com.amazonaws.services.lambda.runtime.LambdaLogger;
    import com.amazonaws.services.lambda.runtime.events.SNSEvent;
    
    public class SNSEventHandler {
    
        public String handleSNSEvent(SNSEvent event, Context context) {
            LambdaLogger logger = context.getLogger();
            for (SNSEvent.SNSRecord record : event.getRecords()) {
                SNSEvent.SNS sns = record.getSNS();
                logger.log("handleSNSEvent received SNS message " + sns.getMessage());
            }
            return "handleSNSEvent finished";
        }
    
    }
    

    SNSEvent data model 表明多个事件可能同时到达处理程序,因此示例显示了对它们的迭代,而不是仅仅假设一个。我还没有在实践中看到这一点,但我的使用量一直很低。

    【讨论】:

    • 我也在 github 上找到了相同的 SNSEvent 类,但是我在 Javadoc 中的任何地方都找不到它......? AWS Docs 中没有对 SNSEvent 的引用,所以我对任何人应该如何找到它感到困惑。我会试一试,然后告诉你。谢谢!
    • 我修改了我的函数以接受 SNSEvent 和 Context 对象,并在执行时记录以下豁免。在类 com.app.LambdaHandler 上加载方法处理程序时出错:类 java.lang.NoClassDefFoundError java.lang.NoClassDefFoundError: com/amazonaws/services/lambda/runtime/events/SNSEvent
    • 听起来运行时在您的 jar 文件中找不到 com.amazonaws.services.lambda.runtime.* 包的已编译 .class 文件。你包括他们吗?
    • 是的,我从 Lambda 控制台下载了函数(到完全不同的机器上)并打开它,果然在 lib 目录中是要导入的包的 jar。我打开 aws-lambda-java-events-1.1.0.jar 并在 /com/amazonaws/services/lambda/runtime/events/ 下找到 SNSEvent.class 文件。我在 Netbeans 中使用 Maven 进行开发,对于 AWS Lambda 我还需要做些什么吗?
    • 既然你回答了我原来的问题(现在我有了一个新问题),我接受了你的回答并提出了一个新问题(stackoverflow.com/questions/32782980/…)。如果您不介意看一下并可能回答这个问题,我将不胜感激。
    猜你喜欢
    • 2020-09-11
    • 2019-01-28
    • 1970-01-01
    • 2015-11-16
    • 2019-12-02
    • 2021-09-03
    • 1970-01-01
    • 2021-10-18
    • 1970-01-01
    相关资源
    最近更新 更多