Bro*_*oks 25 amazon-s3 amazon-web-services 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");
}
Run Code Online (Sandbox Code Playgroud)
我已经注释掉并从这篇文章中排除了所有的逻辑,因为我得到了一个OutOfMemoryError,我已经隔离到了创建AmazonS3Client对象.当我拿出那个物体时,我没有得到错误.上面的确切代码导致OutOfMemoryError.
我为这个函数分配了128MB的内存,真的不足以简单地获取凭据并实例化AmazonS3Client对象吗?
我试过给AmazonS3Client构造函数
new EnvironmentVariableCredentialsProvider()
Run Code Online (Sandbox Code Playgroud)
以及
new InstanceProfileCredentialsProvider()
Run Code Online (Sandbox Code Playgroud)
结果相似.
创建AmazonS3Client对象是否只需要更多内存?
下面是堆栈跟踪:
Metaspace:java.lang.OutOfMemoryError java.lang.OutOfMemoryError:com.fasterxml.jackson.databind.deser.BeanDeserializerBuilder.build(BeanDeserializerBuilder.java:347)中的Metaspace,位于com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.buildBeanDeserializer( BeanDeserializerFactory.java:242)at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.createBeanDeserializer(BeanDeserializerFactory.java:143)at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer2(DeserializerCache.java:409)at com .fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer(DeserializerCache.java:358)位于com.fasterxml.jackson.databind.deser的com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:265) .deserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:245)at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:143)at com.fasterxml.jackson.databind.De serial.Context.findRootValueDeserializer(DeserializationContext.java:439)位于com的com.fasterxml.jackson.databind.ObjectReader._prefetchRootDeserializer(ObjectReader.java:1588),位于com的com.fasterxml.jackson.databind.ObjectReader.(ObjectReader.java:185). quickxml.jackson.databind.ObjectMapper._newReader(ObjectMapper.java:558)at com.fasterxml.jackson.databind.ObjectMapper.reader(ObjectMapper.java:3108)
当我尝试提供InstanceProfileCredentialsProvider或EnvironmentVariableCredentialsProvider时,我得到以下堆栈跟踪:
线程"main"中的异常java.lang.Error:java.lang.OutOfMemoryError:java.lang.Class中java.lang.Class.forName0(Native Method)的lambdainternal.AWSLambda.(AWSLambda.java:62)中的Metaspace. lambdaainternal.LambdaRTEntry.main上的forName(Class.java:348)(LambdaRTEntry.java:94)引起:java.lang.OutOfMemoryError:java.lang.ClassLoader中java.lang.ClassLoader.defineClass1(Native Method)的Metaspace. java.securityClassLoader.defineClass(URLClassLoader.java:467)java.securityClassLoader.defineClass(SecureClassLoader.java:142)中的javaC(ClassLoader.java:763)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位于lambd的java.lang.ClassLoader.loadClass(ClassLoader.java:357)的java.lang.ClassLoader.loadClass(ClassLoader.java:424)中的.net.URLClassLoader.findClass(URLClassLoader.java:361)ainternal.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)lambdainternal.AWSLambda.startRuntime(AWSLambda) .java:219)在lambdainternal.AWSLambda.(AWSLambda.java:60)... 3更多START RequestId:58837136-483e-11e6-9ed3-39246839616a版本:$ LATEST END RequestId:58837136-483e-11e6-9ed3-39246839616a REPORT RequestId:58837136-483e-11e6-9ed3-39246839616a持续时间:15002.92 ms结算时长:15000 ms内存大小:128 MB最大使用内存:50 MB
2016-07-12T14:40:28.048Z 588 37136-483e-11e6-9ed3-39246839616a任务在15.00秒后超时
编辑1如果我将分配给该功能的内存增加到甚至192MB,它的工作正常,但奇怪的是,报告只在云计算日志中使用59MB的内存.我只是丢失了剩下的记忆吗?
Ale*_*ejK 18
在Lambda函数中使用AWS Java SDK时,我一直在观察这一点.在创建任何AWS客户端(同步或异步)时,您可能会从Metaspace中获取.
我相信这是由于Amazon Client在实例化时正在执行的操作,包括AmazonHttpClient创建以及请求处理程序链的动态加载(AmazonEc2Client#init()私有方法的一部分).
报告的内存使用量可能是Heap本身,但可能不包括Metaspace.AWS论坛上有几个主题,但AWS没有就此问题做出回应.
减少冷启动的一种方法是将内存设置为 1536 mb,将超时设置为 15 分钟。这将使专用主机仅运行您的 lambda,而不是在共享主机上运行您的 lambda + 当必须启动新实例时,它将从主机上的缓存复制代码,而不是从 S3 复制。
但这会更贵,如果您不想这样做,请继续阅读下面的内容。
如何减少冷启动时间?
1) 遵循 Lambda 最佳实践:https : //docs.aws.amazon.com/lambda/latest/dg/best-practices.html
2)通过为您的函数选择更大的内存设置将内存视为“电源”设置,因为它也决定了您的函数将接收多少 CPU。
3)通过减少函数 ZIP 的大小这可能意味着减少包含在函数 ZIP 中的依赖项的数量。使用 ProGuard 可以进一步减小 Java JAR 的大小
4)【Java Only】使用字节流接口代替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 Only] 不要使用 Java 8 特性来替换匿名类(lambdas、方法引用、构造函数引用等)我们在内部注意到 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
| 归档时间: |
|
| 查看次数: |
6963 次 |
| 最近记录: |