将文件上传到AWS S3需要大量的CPU。

3
我目前正在开发一款服务器应用程序(JEE),并在上传文件到AWS S3时遇到了一些问题。我使用Java SDK(S3client.putObject)来上传这些文件。当服务器启动时,一切都像预期的那样进行。文件在服务器(EC2实例)中生成,并在几秒钟内上传到S3。但是过了一些天之后,性能大大降低。原本只需要5或6秒钟即可上传的文件现在需要10到30分钟(是的,分钟级别)。我对应用程序进行了分析,发现AWS Java SDK执行上传的部分是罪魁祸首。奇怪的是,CPU利用率接近100%,并保持数分钟。由于这基本上是一个IO操作,我不明白为什么它需要这么多CPU周期才能运行。有人经历过这种情况吗? 在哪里寻找解决方案?

PS: 文件大小介于1到50MB之间。

非常感谢!

更新: 创建文件并将其上传到S3的EC2实例为m1.large。 我正在使用1.6.4 AWS SDK版本。


如果不重新启动应用程序,上传文件所需的时间是否最终会降至“5或6秒”? - Sam I am says Reinstate Monica
不,它没有回来。我需要重新启动应用服务器。 - Cleverson Schmidt
如果您正在使用SSL来访问S3,那么如果您已经采取了其他优化S3性能的步骤,可以考虑使用AES-NI。 - Anthony Neace
@CleversonSchmidt 看起来你可能存在某种资源泄漏问题。 - Sam I am says Reinstate Monica
@HyperAnthony 如果是AES-NI的问题,那不应该每次都发生吗? - Cleverson Schmidt
2个回答

4

我在AWS SDK for .NET中遇到了同样的问题。将50GB文件上传到S3会导致100%的CPU使用率。

我对应用程序进行了分析。

事实证明,这是因为所有AWS API请求都必须进行“签名”,而一个文件 - 特别是一个大文件 - 会通过多个请求和块发送,有时会达到数千个,并且其中一些是同时进行的。然后,每个请求都会通过SHA256哈希并使用IAM凭据进行签名。

限制并发线程的数量,禁用httpS(使用http),限制块的数量,增加块的大小等等。通过这样做,您可以减轻负载,但即使在快速连接上发送(即使从EC2到S3在同一地区),它仍将使用约20-30%的CPU :((


1
我想不出为什么SDK代码会导致您的CPU使用率如此之高。 我的第一个猜测是某种垃圾回收问题。当您上传数据时,您是否将File对象传递给AmazonS3.putObject,或者是某种流(包括FileInputStream)? 流可能有点棘手,因为它们不能保证可重复,并且您必须显式地在ObjectMetadata中提供Content-Length作为上传的一部分,否则SDK必须在内存中缓冲您的上传以计算总长度。那将是我建议首先检查的事情。
另外..您应该查看SDK中的TransferManager API。 它为您提供了一个很好的简单界面,可用于上传和下载文件到/从Amazon S3,并具有多个优化功能。
如果仍然找不到线索,我建议为此制作一个死简单的重现案例。编写一个单独的类文件,只需将随机文件上传到相同的S3键中,并让其运行与应用程序代码相同的持续时间。如果您能在这个简单的设置中重现问题,那么我们可以查看代码并帮助进行调试,但是由于完整应用程序代码涉及的所有其他变量,我们无法做更多的猜测。

非常感谢!我正在将一个Inputstream传递给AmazonS3.putObject并设置内容长度。我会检查TransferManager API,看它是否有帮助。 - Cleverson Schmidt

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