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

Bro*_*oks 7 amazon-web-services amazon-sns aws-lambda

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

我已经设置了一个AWS Lambda函数(用Java编写),它接受POJO以允许自动反序列化JSON.我正在使用的测试JSON位于下方,表示一旦所有内容都启动并运行,将从消息的最终源发送的JSON字符串.

{"sender":"Joe", "id":1, "event":"started", "ticks":2, "time":"20150623T214256Z", "version":"1.0"}
Run Code Online (Sandbox Code Playgroud)

当我通过从Lambda"测试"控制台发布它来测试它时,这非常有效.

我现在尝试通过将Lambda函数订阅到主题来挂钩SNS,我正在从SNS控制台测试它.我尝试使用"原始数据"(没有显示任何结果)和使用"JSON生成器"数据选项生成的JSON发送与上面相同的确切消息,我遇到了SNS似乎的问题将消息发送到Lambda函数,POJO被实例化,但是调用默认构造函数或者使用所有空值调用参数化构造函数.无论哪种方式,当Lambda函数通过在POJO中调用重写的toString()方法来记录消息时,它会为所有变量打印出null,而不会显示任何错误消息.同样,SNS主题配置为记录到Cloudwatch,它也没有报告任何错误.

这是新生成的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\"}", 
}
Run Code Online (Sandbox Code Playgroud)

以下是日志消息.

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  
Run Code Online (Sandbox Code Playgroud)

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" } }
Run Code Online (Sandbox Code Playgroud)

以下是适用的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());
    }
}
Run Code Online (Sandbox Code Playgroud)

.

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 + '}';
}
Run Code Online (Sandbox Code Playgroud)

在做了一些挖掘并查看一些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(我不能相信这是不常见的),我找不到任何指定由哪个对象类型发送的文件. SNS主题为Lambda函数,如果事实上我不应该期望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)
Run Code Online (Sandbox Code Playgroud)

好像运行时环境无法识别SNSEvent?

Jam*_*mes 9

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

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

以下是使用AWS Lambda Java支持库在Java中处理SNS事件的示例Lambda函数.

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

}
Run Code Online (Sandbox Code Playgroud)

SNSEvent数据模型显示,多个事件可能在同一时间到达处理程序,因此样本显示迭代超过他们,而不是仅仅假设之一.我还没有看到它在实践中,但我的用量一直很低.