只需一个API调用即可获取S3上对象的大小

时间:2019-10-22 00:12:18

标签: java amazon-s3 aws-sdk

我有一个Java应用程序,该应用程序通过流提取来压缩S3上的许多对象。因此,为了提高效率,该应用程序不会在本地磁盘上下载对象并再次上传它们,而是以5MB的块流式传输文件并动态压缩它们。我面临的挑战是为了提供此操作的进度,我需要依靠所有对象的总大小,并使用一个计数器来查看将总大小中的多少作为计算进度的来源。

我一直面临的挑战是要获得对象的大小,我需要首先遍历所有对象并逐个获得大小并计算总数,然后再开始该过程。但是,这太慢了,因为可能有数百万个对象,这意味着数百万个API调用。如果我尝试在开始压缩之前计算大小,则此计算过程将花费比实际压缩更多的时间,并且会破坏整个目的。因此,我想知道是否有任何方法可以通过单个API调用传递对象列表并接收总大小。我知道有一种方法可以为所有与该前缀匹配的对象添加一个前缀并使该前缀匹配,但是由于对象可能使用不同的前缀存储,因此这种方法将行不通。

下面的代码段是如何一一获取对象大小的方法:

public Long getObjectSize(AmazonS3Client amazonS3Client, String bucket, String key)
        throws IOException {
    return amazonS3Client.getObjectMetadata(bucket, key).getContentLength();
}

注意:如果我依靠对象的数量来计算进度,那根本就不准确。有些对象是2-3KB,有些则很大(1-2GB)。

1 个答案:

答案 0 :(得分:1)

您可以使用Java 8的Stream API进行迭代,并求出值的总和,或者 也许使用AmazonCloudWatch API帮助您获取BucketSizeBytes指标。 因此,您需要listMetrics并使用BucketSizeBytes来获取GetMetricData。

这里是文档的链接: https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/cloudwatch/AmazonCloudWatch.html#listMetrics-com.amazonaws.services.cloudwatch.model.ListMetricsRequest- https://docs.aws.amazon.com/AmazonS3/latest/dev/cloudwatch-monitoring.html

以下是AmazonCloudWatch的一些示例: https://www.javatips.net/api/com.amazonaws.services.cloudwatch.model.metric https://www.programcreek.com/java-api-examples/?api=com.amazonaws.services.cloudwatch.AmazonCloudWatchClient

更新:

就像我在其中一条评论中告诉您的那样,您也可以使用命令行界面。 在这种情况下,您还可以使用cloudwatch,但是通过aws cli会收到JSON响应格式。 我在其中一个链接中提供了一个示例,如下所示:

aws cloudwatch get-metric-statistics --metric-name BucketSizeBytes
--namespace AWS/S3 --start-time 2016-10-19T00:00:00Z --end-time 2016-10-20T00:00:00Z --statistics Average --unit Bytes --region us-west-2 --dimensions Name=BucketName,Value=ExampleBucket Name=StorageType,Value=StandardStorage --period 86400 --output json

此其他链接有更多说明: http://cloudsqale.com/2018/10/08/s3-monitoring-step-1-bucket-size-and-number-of-objects/

总而言之,似乎使用cloudwatch是避免重复调用的最简单方法。