在适用于 Java 的 亚马逊云科技 开发工具包 2.x 中引入基于 CRT 的 S3 客户端和 S3 传输管理器

作者: Zoe Wang | 2022

我们很高兴地宣布,适用于 Java 的 亚马逊云科技 开发工具包 2.x 中的两项新功能已正式上线,它们支持使用 亚马逊简单存储服务 (Amazon S3) 加速对象传输:基于 亚马逊云科技 通用运行时 (CRT) 的 S3 软件开发工具包客户端,以及 S3 传输管理器。

基于 CRT 的 S3 客户端允许您通过自动利用 Amazon S3 分段 上 传 API 字节 范围提取,在增强性能和可靠性的情况下向 Amazon S3 传输对象。 它实现了与现有 S3 异步客户端相同的接口,开箱即用可提高吞吐量。

S3 传输管理器是基于 S3 客户端构建的高级传输实用程序。它提供了一个简单的 API,允许您在应用程序和 Amazon S3 之间传输文件和目录。S3 Transfer Manager 还使您能够实时监控传输进度,并暂停传输以便稍后执行。

下表显示了这两个新功能的用例。

这篇文章将引导您了解这些新增功能的主要功能,并向您展示如何使用它们。

主要特点

提高了上传、下载和复制的吞吐量

对于上传或复制 S3 对象请求,基于 CRT 的 S3 客户端可以将单个 p utObject 或 CopyObject 请求转换为 多个 Multi p artUpload 请求,并行发送这些请求以提高性能。

对于下载 S3 对象请求,基于 CRT 的 S3 客户端可以在提高性能时将 GetObject 请求拆分为多个较小的请求。这些请求将并行传输对象的不同部分,以实现更高的聚合吞吐量。

此外,如果出现网络故障,基于 CRT 的 S3 客户端无需重新开始整个传输即可重试各个故障部件,从而提高了传输可靠性。

我们已经进行了性能测试,将基于 CRT 的 S3 客户端与用于 getObject 、 put Object 和 CopyObjec t 操作的现有 S3 异步客户端进行了比较。 根据我们的测试,基于 CRT 的 S3 客户端对于 256MB 的对象具有更好的性能。下表显示了这三项操作的改进百分比。我们希望客户看到更大尺寸的物体有更大的改进。

增强的连接管理

基于 CRT 的 S3 客户端提供增强的连接池和域名系统 (DNS) 负载平衡。在幕后,基于 CRT 的 S3 客户端构建了一个亚马逊 S3 服务器 IP 池,并在多个亚马逊 S3 终端节点之间实现负载平衡。这提高了超出单个服务器 IP 所能提供的吞吐量,并允许在极少数情况下出现缓慢的端点或服务器中断时自动进行故障转移。

更快的启动时间

使用基于 CRT 的 S3 客户端,您可以从更快的启动时间中获益。我们已经观察到,在现有 S3 客户端和基于 CRT 的新型 S3 客户端之间,亚马逊云科技 Lambda 的启动性能提高了多达 68%。请注意,结果可能因您的应用程序配置而异。

下图比较了使用现有 S3 异步客户端和基于 CRT 的新型 S3 客户端 调用 L istBuckets API 的 亚马逊云科技 Lambda 冷启动时长。

入门

基于CRT的S3客户端

为基于 CRT 的 S3 客户端添加依赖关系

首先,你需要向项目添加两个依赖关系。在 Maven 中央存储库中搜索 s 3 和 a ws- crt 工件的最新版本。

<dependency>
  <groupId>software.amazon.awssdk</groupId>
  <artifactId>s3</artifactId>
  <version>${aws.sdk.version}</version>
</dependency>
<dependency>
  <groupId>software.amazon.awssdk.crt</groupId>
  <artifactId>aws-crt</artifactId>
  <version>${aws.crt.version}</version>
</dependency>

实例化基于 CRT 的 S3 客户端

您可以使用默认设置轻松实例化基于 CRT 的 S3 客户端。

S3AsyncClient s3AsyncClient = S3AsyncClient.crtCreate();

如果需要配置客户端,则可以使用客户端生成器。通过更改生成器方法,您可以轻松地从基于 Java 的 S3 客户端切换到基于 CRT 的客户端。请注意,CRT 生成器目前可能不支持标准生成器中可用的某些设置。

S3AsyncClient s3AsyncClient = 
       S3AsyncClient.crtBuilder()
                    .credentialsProvider(DefaultCredentialsProvider.create())
                    .region(Region.US_WEST_2)
                    .targetThroughputInGbps(20.0)
                    .minimumPartSizeInBytes(8 * MB)
                    .build();

调用 S3 API

您可以使用基于 CRT 的 S3 客户端来调用任何 Amazon S3 API。在下一节中,我们将向您展示如何调用 putObject 和 getObject

S3AsyncClient s3Client = S3AsyncClient.crtCreate();

// Upload a local file to Amazon S3
PutObjectResponse putObjectResponse = 
      s3Client.putObject(req -> req.bucket("myBucket")
                                   .key("myKey"),
                        AsyncRequestBody.fromFile(Paths.get("myFile.txt")))
              .join();

// Download an object from Amazon S3 to a local file
GetObjectResponse getObjectResponse = 
     s3Client.getObject(req -> req.bucket("myBucket")
                                  .key("myKey"),
                        AsyncResponseTransformer.toFile(Paths.get("myFile.txt")))
             .join();

S3 传输管理器

为 S3 传输管理器添加依赖关系

首先,你需要在项目中包含 s3-transfer-manager 和 aws- crt 依赖关系 在 Maven 中央存储库中搜索 s3-transfer-manager 和 aws- crt 工件的最新版本。

<dependency>
  <groupId>software.amazon.awssdk</groupId>
  <artifactId>s3-transfer-manager</artifactId>
  <version>${aws.sdk.version}</version>
</dependency>
<dependency>
  <groupId>software.amazon.awssdk.crt</groupId>
  <artifactId>aws-crt</artifactId>
  <version>${aws.crt.version}</version>
</dependency>

将 S3 传输管理器实例化

您可以使用以下代码段使用默认设置实例化传输管理器。

S3TransferManager transferManager = S3TransferManager.create();

如果您想配置设置或使用已经构建的基于 CRT 的底层 S3 客户端,我们建议改用构建器:

S3AsyncClient s3AsyncClient = 
    S3AsyncClient.crtBuilder()
                 .credentialsProvider(DefaultCredentialsProvider.create())
                 .region(Region.US_WEST_2)
                 .targetThroughputInGbps(20.0)
                 .minimumPartSizeInBytes(8 * MB)
                 .build();

S3TransferManager transferManager =
    S3TransferManager.builder()
                     .s3Client(s3AsyncClient)
                     .build();

传输单个对象

将文件上传到 S3 并使用 TransferListener 记录上传进度

要将文件上传到 Amazon S3,您需要提供源文件路径和 指定目标存储桶和密钥的 putObjectRequest 。或者,你可以通过附加 T r ansferListener 来监控传输进度。提供的 LoggingTransferListener 会 记录基本的进度条;用户也可以实现自己的监听器

S3TransferManager transferManager = S3TransferManager.create();

UploadFileRequest uploadFileRequest = 
    UploadFileRequest.builder()
                     .putObjectRequest(req -> req.bucket("bucket").key("key"))
                     .addTransferListener(LoggingTransferListener.create())
                     .source(Paths.get("myFile.txt"))
                     .build();

FileUpload upload = transferManager.uploadFile(uploadFileRequest);

// Wait for the transfer to complete
upload.completionFuture().join();

将 S3 对象下载到本地文件并使用 TransferListener 记录下载进度

要下载对象,您需要提供目标文件路径和 指定源存储桶和密钥的 getObjectRequest 。与上传一样,你可以通过附加 T r ansferListener 来监控传输进度。

S3TransferManager transferManager = S3TransferManager.create();

DownloadFileRequest downloadFileRequest = 
    DownloadFileRequest.builder()
                       .getObjectRequest(req -> req.bucket("bucket").key("key"))
                       .destination(Paths.get("myFile.txt"))
                       .addTransferListener(LoggingTransferListener.create())
                       .build();

FileDownload download = transferManager.downloadFile(downloadFileRequest);

// Wait for the transfer to complete
download.completionFuture().join();

将 S3 对象从一个位置复制到另一个位置

要复制对象,您需要为 CopyObjectRequest 提供源和目标位置。

S3TransferManager transferManager = S3TransferManager.create();
CopyObjectRequest copyObjectRequest = CopyObjectRequest.builder()
                                                       .sourceBucket("source_bucket")
                                                       .sourceKey("source_key")
                                                       .destinationBucket("dest_bucket")
                                                       .destinationKey("dest_key")
                                                       .build();
CopyRequest copyRequest = CopyRequest.builder()
                                     .copyObjectRequest(copyObjectRequest)
                                     .build();

Copy copy = transferManager.copy(copyRequest);

// Wait for the transfer to complete
CompletedCopy completedCopy = copy.completionFuture().join();

在同一个目录中传输多个对象

将本地目录上传到 S3 存储桶

要以递归方式将本地目录上传到 S3 存储桶,您需要提供源目录和目标存储桶。

S3TransferManager transferManager = S3TransferManager.create();
DirectoryUpload directoryUpload =
    transferManager.uploadDirectory(UploadDirectoryRequest.builder()
                                                          .source(Paths.get("source/directory"))
                                                          .bucket("bucket")
                                                          .build());

// Wait for the transfer to complete
CompletedDirectoryUpload completedDirectoryUpload = directoryUpload.completionFuture().join();

// Print out the failed uploads
completedDirectoryUpload.failedTransfers().forEach(System.out::println);

将同一存储桶中的 S3 对象下载到本地目录

要下载同一个存储桶中的所有 S3 对象,您需要提供目标目录和源存储桶。

S3TransferManager transferManager = S3TransferManager.create();
DirectoryDownload directoryDownload =
    transferManager.downloadDirectory(DownloadDirectoryRequest.builder()
                                                              .destination(Paths.get("destination/directory"))
                                                              .bucket("bucket")
                                                              .build());
// Wait for the transfer to complete
CompletedDirectoryDownload completedDirectoryDownload = directoryDownload.completionFuture().join();

// Print out the failed downloads
completedDirectoryDownload.failedTransfers().forEach(System.out::println);

结论

在这篇博客文章中,我们讨论了基于 CRT 的 S3 客户端和适用于 Java 的 亚马逊云科技 开发工具包 2. x 中的 S3 传输管理器的关键功能。我们向您展示了使用它们来传输对象是多么容易。要了解有关如何设置和开始使用这些功能的更多信息,请访问我们的 开发者指南 API 参考 。今天就试试吧,告诉我们你的想法!您可以通过在我们的 GitHub 存储库 上创建问题来联系我们。

Zoe Wang

Zoe Wang

Zoe 是一名软件开发工程师,正在开发适用于 Java 的 亚马逊云科技 开发工具包。她热衷于开发改善开发者体验的工具。你可以在 GitHub 上找到她 @zoewangg