在Lambda

时间:2016-07-13 03:55:48

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

我有一个AWS Lambda函数,配置只有128MB内存,由SNS(它本身由S3触发)触发,并将从S3下载该文件。

在我的功能中,我有以下内容:

public class LambdaHandler {

    private final AmazonS3Client s3Client = new AmazonS3Client();

    public void gdeltHandler(SNSEvent event, Context context) {
        System.out.println("Starting");
        System.out.println("Found " + eventFiles.size() + " event files");
    }

我已经注释掉并从这篇文章中排除了所有逻辑,因为我得到的OutOfMemoryError已经与创建AmazonS3Client对象隔离了。当我拿出那个物体时,我没有得到错误。上面的确切代码导致OutOfMemoryError。

我为该函数分配了128MB的内存,这真的不足以简单地获取凭据并实例化AmazonS3Client对象吗?

我尝试过提供AmazonS3Client构造函数

new EnvironmentVariableCredentialsProvider()

以及

new InstanceProfileCredentialsProvider()

有类似的结果。

创建AmazonS3Client对象是否只需要更多内存?

下面是堆栈跟踪:

  

Metaspace:java.lang.OutOfMemoryError java.lang.OutOfMemoryError:   Metaspace at   com.fasterxml.jackson.databind.deser.BeanDeserializerBuilder.build(BeanDeserializerBuilder.java:347)   在   com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.buildBeanDeserializer(BeanDeserializerFactory.java:242)   在   com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.createBeanDeserializer(BeanDeserializerFactory.java:143)   在   com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer2(DeserializerCache.java:409)   在   com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer(DeserializerCache.java:358)   在   com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:265)   在   com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:245)   在   com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:143)   在   com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:439)   在   com.fasterxml.jackson.databind.ObjectReader._prefetchRootDeserializer(ObjectReader.java:1588)   在   com.fasterxml.jackson.databind.ObjectReader。(ObjectReader.java:185)   在   com.fasterxml.jackson.databind.ObjectMapper._newReader(ObjectMapper.java:558)   在   com.fasterxml.jackson.databind.ObjectMapper.reader(ObjectMapper.java:3108)

当我尝试提供InstanceProfileCredentialsProvider或EnvironmentVariableCredentialsProvider时,我得到以下堆栈跟踪:

  

线程中的异常" main" java.lang.Error的:   java.lang.OutOfMemoryError:Metaspace at   lambdainternal.AWSLambda。(AWSLambda.java:62)at   java.lang.Class.forName0(Native Method)at   java.lang.Class.forName(Class.java:348)at   lambdainternal.LambdaRTEntry.main(LambdaRTEntry.java:94)引起:   java.lang.OutOfMemoryError:Metaspace at   java.lang.ClassLoader.defineClass1(Native Method)at   java.lang.ClassLoader.defineClass(ClassLoader.java:763)at   java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)     在java.net.URLClassLoader.defineClass(URLClassLoader.java:467)at   java.net.URLClassLoader.access $ 100(URLClassLoader.java:73)at   java.net.URLClassLoader $ 1.run(URLClassLoader.java:368)at   java.net.URLClassLoader $ 1.run(URLClassLoader.java:362)at   java.security.AccessController.doPrivileged(Native Method)at   java.net.URLClassLoader.findClass(URLClassLoader.java:361)at   java.lang.ClassLoader.loadClass(ClassLoader.java:424)at   java.lang.ClassLoader.loadClass(ClassLoader.java:357)at   lambdainternal.EventHandlerLoader $ PojoMethodRequestHandler.makeRequestHandler(EventHandlerLoader.java:421)     在   lambdainternal.EventHandlerLoader.getTwoLengthHandler(EventHandlerLoader.java:777)     在   lambdainternal.EventHandlerLoader.getHandlerFromOverload(EventHandlerLoader.java:802)     在   lambdainternal.EventHandlerLoader.loadEventPojoHandler(EventHandlerLoader.java:888)     在   lambdainternal.EventHandlerLoader.loadEventHandler(EventHandlerLoader.java:740)     在   lambdainternal.AWSLambda.findUserMethodsImmediate(AWSLambda.java:126)     在lambdainternal.AWSLambda.findUserMethods(AWSLambda.java:71)at   lambdainternal.AWSLambda.startRuntime(AWSLambda.java:219)at   lambdainternal.AWSLambda。(AWSLambda.java:60)......还有3个START   RequestId:58837136-483e-11e6-9ed3-39246839616a版本:$ LATEST END   RequestId:58837136-483e-11e6-9ed3-39246839616a报告RequestId:   58837136-483e-11e6-9ed3-39246839616a Duration:15002.92 ms Billed   持续时间:15000毫秒内存大小:128 MB最大使用内存:50 MB
  2016-07-12T14:40:28.048Z 58837136-483e-11e6-9ed3-39246839616a任务   15点后超时

编辑1 如果我将分配给该功能的内存增加到192MB,它可以正常工作,但奇怪的是,报告只在云计算日志中使用59MB内存。我只是丢失了其余的记忆吗?

3 个答案:

答案 0 :(得分:18)

在Lambda函数中使用AWS Java SDK时,我一直在观察这一点。 在创建任何AWS客户端(同步或异步)时,您可能会离开Metaspace。

我认为这是由于亚马逊客户端在实例化时正在执行的操作,包括创建AmazonHttpClient以及动态加载请求处理程序链(AmazonEc2Client#init()私有方法的一部分)。

报告的内存使用量可能是Heap本身,但可能不包括Metaspace。 AWS论坛上有几个主题,但AWS没有就此问题做出回应。

答案 1 :(得分:4)

尝试将分配给lambda的内存从128增加到256 MB

答案 2 :(得分:1)

如何减少冷启动时间?

1)遵循Lambda最佳做法: https://docs.aws.amazon.com/lambda/latest/dg/best-practices.html

2)通过为功能选择更大的内存设置 将内存视为“电源”设置,因为它还决定了函数将接收多少CPU。

3)通过减小功能ZIP的大小 这可能意味着减少您在函数ZIP中包含的依赖项数量。 使用ProGuard可以进一步减小Java JAR的大小

4)[仅Java]使用字节流接口代替POJO接口。 Lambda内部使用的JSON序列化库可能需要一些时间才能启动。这将需要您完成开发工作,但是您可以通过使用字节流接口和轻量级JSON库来对此进行改进。以下一些链接可能会有所帮助: http://docs.aws.amazon.com/lambda/latest/dg/java-handler-io-type-stream.html https://github.com/FasterXML/jackson-jr

5)[仅Java]不要使用Java 8功能来替代匿名类(lambda,方法引用,构造函数引用等)。 我们在内部注意到与Java 8 Lambda相关的字节码似乎导致次优的启动性能。如果您的代码使用的任何Java 8功能都可以替换匿名类(lambda,方法引用,构造函数引用等),则可以通过返回到匿名类来缩短启动时间。

6)通过使用其他运行时 不同的运行时具有不同的冷启动时间和不同的运行时性能。虽然NodeJS可能适合繁重的IO工作,但Go可能适合执行大量并发工作的代码。客户已经完成了一些基本基准测试以比较Lambda上的语言性能,这是对不同编程语言性能的更一般的比较。没有一个万能的答案,请使用适合您要求的答案。

基本基准:https://read.acloud.guru/comparing-aws-lambda-performance-of-node-js-python-java-c-and-go-29c1163c2581

一般比较:https://benchmarksgame-team.pages.debian.net/benchmarksgame/which-programs-are-fast.html