AWS Lambda发布到SNS时超时问题

12

我想从Lambda函数调用中发布一些数据到SNS,但似乎并没有起作用。我的函数代码是 -

public class Handler implements RequestHandler<DynamodbEvent, Void> {

    private static final String SNS_TOPIC_ARN = "arn:aws:sns:us-west-2:account_number:function_name";

    @Override
    public Void handleRequest(DynamodbEvent dynamodbEvent, Context context) {

        LambdaLogger logger = context.getLogger();

        AmazonSNSClient snsClient = new AmazonSNSClient(new DefaultAWSCredentialsProviderChain());
        snsClient.setRegion(Region.getRegion(Regions.US_WEST_2));

        for (DynamodbStreamRecord record : dynamodbEvent.getRecords()) {
            Map<String, AttributeValue> newImage = record.getDynamodb().getNewImage();

            if (newImage == null) {
                continue;
            }

            String sensorId = newImage.get("sensorID").getS();
            long timestamp = Long.parseLong(newImage.get("timestamp").getS());
            double temperature = Double.parseDouble(newImage.get("payload").getM().get("temp").getN());

            String data = sensorId + " " + timestamp + " " + temperature;

            logger.log(data);

            PublishRequest publishRequest = new PublishRequest(SNS_TOPIC_ARN, data);

            PublishResult publishResult = snsClient.publish(publishRequest);

            logger.log("Publish Successful " + publishResult.getMessageId());
        }

        snsClient.shutdown();

        return null;
    }
}

这个调用导致超时(10秒),Lambda函数执行失败。如果我注释掉SNS发布部分,也就是说,如果我只记录从DynamoDB接收到的数据,它就可以正常工作。一旦添加了SNS发布代码,它就会超时。

在CloudWatch中记录的超时消息为 -

START RequestId: 8db74187-459b-42c5-8a06-b3a74873b236 Version: $LATEST END RequestId: 8db74187-459b-42c5-8a06-b3a74873b236 REPORT RequestId: 8db74187-459b-42c5-8a06-b3a74873b236 Duration: 10001.66 ms Billed Duration: 10000 ms Memory Size: 128 MB Max Memory Used: 37 MB Task timed out after 10.00 seconds

我已经设置了所有必要的权限,并且可以使用以下代码在我的PC上发布到SNS -

PublishRequest publishRequest = new PublishRequest(SNS_TOPIC_ARN, data);
PublishResult publishResult = snsClient.publish(publishRequest);
System.out.println("Publish Successful " + publishResult.getMessageId());

我还尝试使用 AmazonSNSAsyncClient 而不是 AmazonSNSClient,但结果相同。

我错过了什么?


尝试将分配的内存设置增加到最大值。这将加快执行SNS API调用所需的处理速度。您目前将其设置为最慢的设置。然后尝试增加超时秒数。每个AWS Lambda函数调用中超时的DynamoDB事件数量是多少? - Eric Hammond
@EricHammond,每次 Lambda 调用我只收到一个事件。我怀疑这不需要更多的内存和时间。负载也非常小。此外,当我添加 SNS 部分时,甚至第一次调用 logger.log()(记录接收到的数据的函数)也没有被执行到。 - Rohan
Java函数在Lambda上启动速度肯定比NodeJS或Python函数慢,并且需要更多的内存。我建议首先增加超时时间和可用内存。 - Mark B
1
超时也可能是由于使用AWS SDK的请求失败,它们会自动使用指数退避进行重试。如果资源不存在、存在权限问题或服务实际上已经停止,这种情况可能会发生。将Lambda函数超时设置为一分钟以上,或更改SDK重试逻辑,以完全避免这种类型的超时。 - JaredHatfield
看起来最终是内存问题。谢谢大家。你们能否有人把它发布为答案? - Rohan
4个回答

10

好的,既然没有评论我的问题的人回答,我自己来回答。

将内存使用量增加到256 MB并将超时时间设为30秒似乎解决了这个问题。


在哪里明确地增加了内存使用和超时时间? - TheQ
8
针对未来读者:如果您的 Lambda 缺少 NAT 网关,则很可能是网络问题。请参见例如 https://dev59.com/zaDia4cB1Zd3GeqPEXtM#43234476。 - luk2302

2
增加Lambda操作分配的内存量。

0

将分配给 Lambda 函数的内存增加也对我有用(此设置在 Lambda 控制台的基本设置下)。

这个问题让我非常疯狂 - 我正在为两个不同的 Lambda 函数使用相同的 JAR 文件,并且它们的配置完全相同,但是 SNS 调用对其中一个函数有效,而对另一个函数则超时。真是令人发疯!


0
在我的情况下,问题是一个网络问题。如果VPC缺少NAT网关,那么VPC中的Lambda通常无法访问网络。这会阻止SNS的触发。
您可以通过为Amazon SNS创建一个Amazon VPC终端节点来解决此问题:
  • 在Amazon VPC控制台中,创建一个新的终端节点
  • 选择AWS服务com.amazonaws.<your-region>.sns
  • 选择您的Lambda VPC,所有子网和安全组
一旦建立了这个AWS PrivateLink,我的Lambda函数中的SNS通知立即开始工作,而无需对SNS或Lambda本身进行进一步更改。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接