AWS SNS 发布到订阅的 Lambda 函数记录空字段

2024-05-08

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

我设置了一个 AWS Lambda 函数(用 Java 编写),该函数接受 POJO 以允许自动反序列化 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 被实例化,但要么调用默认构造函数,要么使用所有 null 值调用参数化构造函数。无论哪种方式,当 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\"}", 
}

以下是日志消息。

拉姆达的日志:

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  

社交网络日志:

{ "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。爪哇 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 文档来记录用于接收反序列化 POJO 的 Java Lambda 函数设置(我不敢相信这如此罕见),而且我找不到任何指定该对象发送的对象类型的内容。 SNS 主题到 Lambda 函数,如果事实上我不应该期望 POJO 类型。

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

任何帮助,将不胜感激。

EDIT 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?


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

  1. 您的消息类别不符合预期Lambda POJO 格式 http://docs.aws.amazon.com/lambda/latest/dg/java-handler-io-type-pojo.htmlLambda 将用于反序列化事件对象的 getX/setX 访问器的数量。
  2. 如果您的事件来自 SNS,它将遵循通用 SNS 对象格式而不是您的自定义格式。您必须检查 SNS 事件才能在Message,然后单独解析。查看 Lambda 中操作 > 配置示例事件下的 SNS 事件模板。

以下是用于在 Java 中处理 SNS 事件的示例 Lambda 函数,使用AWS Lambda Java 支持库 https://github.com/aws/aws-lambda-java-libs.

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";
    }

}

The SNS事件数据模型 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表明多个事件可能同时到达处理程序,因此该示例显示了对它们进行迭代,而不是仅仅假设一个事件。我还没有在实践中看到这一点,但我的使用量很小。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

AWS SNS 发布到订阅的 Lambda 函数记录空字段 的相关文章

随机推荐