

# 最佳实践设计模式：优化 Amazon S3 性能
<a name="optimizing-performance"></a>

当从 Amazon S3 上传和检索存储时，您的应用程序可以轻松地实现每秒数千个事务的请求性能。Amazon S3 自动扩展到高请求速率。例如，您的应用程序可以实现每秒每个分区的 Amazon S3 前缀至少 3500 个PUT/COPY/POST/DELETE 或 5500 个 GET/HEAD 请求。对存储桶中的前缀数量没有限制。您可以通过使用并行来增加读取或写入性能。例如，如果您在 Amazon S3 存储桶中创建 10 个前缀以并行处理读取，则可以将读取性能扩展到每秒 55,000 个读取请求。同样，您可以通过写入多个前缀来扩展写入操作。在读写操作的情况下，扩展是逐渐发生的，而不是瞬时完成的，实际性能将根据您的特定工作负载特征、使用规律和系统配置而有所不同。当 Amazon S3 扩展到新的更高请求速率时，您可能会看到一些 503（减速）错误。扩展完成后，这些错误将消失。有关创建和使用前缀的更多信息，请参阅[使用前缀组织对象](using-prefixes.md)。

Amazon S3 上的某些数据湖应用程序对于运行超过 PB 级数据的查询扫描数百万或数十亿个对象。这些数据湖应用程序实现的单一实例传输速率可最大限度地提高 [Amazon EC2](https://docs.aws.amazon.com/ec2/index.html) 实例的网络接口利用率，这在单一实例上可高达 100 Gb/s。然后，这些应用程序跨多个实例聚合吞吐量，以获得每秒多个 Tb 的级别。

另外一些应用程序对延迟很敏感，例如社交媒体消息传递应用程序。这些应用程序可实现一致的小对象延迟（对于较大对象，为第一个字节输出延迟），延迟时间大约为 100 - 200 毫秒。

其他 AWS 服务也可帮助加快不同应用程序架构的性能。例如，如果您希望通过单一 HTTP 连接实现较高的传输速率，或需要单一位毫秒延迟，请使用 [Amazon CloudFront](https://docs.aws.amazon.com/cloudfront/index.html) 或 [Amazon ElastiCache](https://docs.aws.amazon.com/elasticache/index.html) 以通过 Amazon S3 进行缓存。

此外，如果您希望在客户端与 S3 存储桶之间获得较快的长距离数据传输速度，请使用 [使用 Amazon S3 Transfer Acceleration 配置快速、安全的文件传输](transfer-acceleration.md)。Transfer Acceleration 使用 CloudFront 中的全球分布式边缘站点来加快跨地理距离的数据传输。如果 Amazon S3 工作负载使用具有 AWS KMS 的服务器端加密，请参阅《AWS Key Management Service 开发人员指南》中的 [AWS KMS 限制](https://docs.aws.amazon.com/kms/latest/developerguide/limits.html)，以获取有关使用案例支持的请求速率的信息。

下面的主题介绍的最佳实践准则和设计模式用于优化使用 Amazon S3 的应用程序的性能。有关对 Amazon S3 进行性能优化的最新信息，请参阅 [Amazon S3 的性能准则](optimizing-performance-guidelines.md) 和 [Amazon S3 的性能设计规律](optimizing-performance-design-patterns.md)。

**注意**  
有关将 Amazon S3 Express One Zone 存储类与目录存储桶配合使用的更多信息，请参阅 [S3 Express One Zone](directory-bucket-high-performance.md#s3-express-one-zone) 和[使用目录存储桶](directory-buckets-overview.md)。

**Topics**
+ [Amazon S3 的性能准则](optimizing-performance-guidelines.md)
+ [Amazon S3 的性能设计规律](optimizing-performance-design-patterns.md)

  


# Amazon S3 的性能准则
<a name="optimizing-performance-guidelines"></a>

当构建用于从 Amazon S3 上传和检索对象的应用程序时，请遵循我们的最佳实践准则以优化性能。我们还提供了更详细的 [Amazon S3 的性能设计规律 ](optimizing-performance-design-patterns.md)。

要在 Amazon S3 上获得应用程序的最佳性能，我们建议遵循以下准则。

**Topics**
+ [衡量性能](#optimizing-performance-guidelines-measure)
+ [水平扩展存储连接](#optimizing-performance-guidelines-scale)
+ [使用字节范围提取](#optimizing-performance-guidelines-get-range)
+ [延迟敏感型应用程序的重试请求](#optimizing-performance-guidelines-retry)
+ [在同一 AWS 区域中结合 Amazon S3（存储）和 Amazon EC2（计算）](#optimizing-performance-guidelines-combine)
+ [使用 Amazon S3 Transfer Acceleration 最大限度地减少因距离导致的延迟](#optimizing-performance-guidelines-acceleration)
+ [使用最新版本的 AWS SDK](#optimizing-performance-guidelines-sdk)

## 衡量性能
<a name="optimizing-performance-guidelines-measure"></a>

当优化性能时，查看网络吞吐量、CPU 和 DRAM 要求。根据针对这些不同资源的组合需求，可能需要评估不同的 [Amazon EC2](https://docs.aws.amazon.com/ec2/index.html) 实例类型。有关实例类型的信息，请参阅《Amazon EC2 用户指南》**中的[实例类型](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/instance-types.html)。

它还有助于在衡量性能时使用 HTTP 分析工具查看 DNS 查找时间、延迟和数据传输速度。

 要了解性能要求并优化应用程序的性能，还可以监控收到的 503 错误响应。监控某些性能指标可能会产生额外费用。有关更多信息，请参阅 [Amazon S3 定价](https://aws.amazon.com/s3/pricing/)。

### 监控 503（减速）状态错误响应的数量
<a name="optimizing-performance-guidelines-measure-503"></a>

 要监控收到的 503 状态错误响应的数量，可以使用以下选项之一：
+ 使用 Amazon S3 的 Amazon CloudWatch 请求指标。CloudWatch 请求指标包括一个用于 5xx 状态响应的指标。有关 CloudWatch 请求指标的更多信息，请参阅[使用 Amazon CloudWatch 监控指标](cloudwatch-monitoring.md)。
+ 使用 Amazon S3 Storage Lens 存储统计管理工具的高级指标部分中提供的 503（服务不可用）错误计数。有关更多信息，请参阅 [使用 S3 Storage Lens 存储统计管理工具指标提高性能](storage-lens-detailed-status-code.md)。
+ 使用 Amazon S3 服务器访问日志记录。通过服务器访问日志记录，您可以筛选和查看所有收到 503（内部错误）响应的请求。还可以使用 Amazon Athena 解析日志。有关服务器访问日志记录的更多信息，请参阅 [使用服务器访问日志记录来记录请求](ServerLogs.md)。

 通过监控 HTTP 503 状态错误代码的数量，您通常可以获得宝贵的见解，了解哪些前缀、密钥或存储桶获得的节流请求最多。

## 水平扩展存储连接
<a name="optimizing-performance-guidelines-scale"></a>

跨许多连接分布请求是一种常用的横向扩展性能的设计模式。当构建高性能应用程序时，将 Amazon S3 视为非常大的分布式系统，而不是类似于传统存储服务器的单个网络端点。您可以通过将多个并行请求发到 Amazon S3 来实现最佳性能。将这些请求分布在不同的连接，以最大限度地利用 Amazon S3 的可访问带宽。Amazon S3 对与存储桶建立的连接数没有任何限制。

## 使用字节范围提取
<a name="optimizing-performance-guidelines-get-range"></a>

通过在 [GET Object](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectGET.html) 请求中使用 `Range` HTTP 标头，您可以从对象中提取字节范围，而只传输指定的部分。您可以使用到 Amazon S3 的并行连接，从相同对象中提取不同的字节范围。这有助于您通过单一整个对象请求实现更高的聚合吞吐量。通过提取较小范围的大型对象，您的应用程序还可以在请求中断时改善重试次数。有关更多信息，请参阅 [下载对象](download-objects.md)。

如果使用分段上传来 PUT 对象，则最佳实践是以相同的分段大小来 GET 它们（或者至少与分段边界相符）以获得最佳性能。GET 请求可以直接面向单独的分段；例如，`GET ?partNumber=N.`

## 延迟敏感型应用程序的重试请求
<a name="optimizing-performance-guidelines-retry"></a>

大量的超时和重试会导致持续不断的延迟。考虑到 Amazon S3 的大规模，如果第一个请求较慢，则退出的请求可能采取不同的路径并快速成功。AWS SDK 具有可配置的超时和重试值，您可以进行调整以符合特定应用程序的容限。

## 在同一 AWS 区域中结合 Amazon S3（存储）和 Amazon EC2（计算）
<a name="optimizing-performance-guidelines-combine"></a>

尽管 S3 存储桶名称是全局唯一的，但每个存储桶都存储在您创建它时所选择的区域中。要了解有关存储桶命名准则的更多信息，请参阅[存储桶概述](https://docs.aws.amazon.com/AmazonS3/latest/userguide/UsingBucket.html)和[存储桶命名规则](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucketnamingrules.html)。为了优化性能，我们建议您尽可能从位于同一 AWS 区域的 Amazon EC2 实例中访问此存储桶。这可以减少网络延迟和数据传输成本。

有关数据传输成本的更多信息，请参阅 [Amazon S3 定价](https://aws.amazon.com/s3/pricing/)。

## 使用 Amazon S3 Transfer Acceleration 最大限度地减少因距离导致的延迟
<a name="optimizing-performance-guidelines-acceleration"></a>

[使用 Amazon S3 Transfer Acceleration 配置快速、安全的文件传输](transfer-acceleration.md) 可在客户端与 S3 存储桶之间管理快速、轻松和安全的长地理距离文件传输。Transfer Acceleration 利用 [Amazon CloudFront](https://docs.aws.amazon.com/cloudfront/index.html) 中的全球分布式边缘站点。当数据到达某个边缘站点时，会通过经过优化的网络路径路由至 Amazon S3。Transfer Acceleration 适合定期跨大洲传输 GB 到 TB 的数据。它也适用于全球各地需要上传到集中式存储桶的客户。

可以使用 [Amazon S3 Transfer Acceleration 速度比较工具](https://s3-accelerate-speedtest.s3-accelerate.amazonaws.com/en/accelerate-speed-comparsion.html)来比较各个 Amazon S3 区域内加快的上传速度和未加快的上传速度。此速度比较工具使用分段上传来将文件从浏览器传输到各种使用和未使用 Amazon S3 Transfer Acceleration 的 Amazon S3 区域。

## 使用最新版本的 AWS SDK
<a name="optimizing-performance-guidelines-sdk"></a>

AWS SDK 为许多用于优化 Amazon S3 性能的建议准则提供内置的支持。这些 SDK 提供了更简单的 API 以便从应用程序内部利用 Amazon S3，并定期更新以遵循最新的最佳实践。例如，这些 SDK 包含自动对 HTTP 503 错误重试请求的逻辑，并投资编写代码来应对和适应慢速连接。

这些 SDK 还提供[传输管理器](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/examples-s3-transfermanager.html)，以便在适当的时机使用字节范围请求来自动横向扩展连接，从而实现每秒数千个请求。务必使用最新版本的 AWS SDK，以获取最新的性能优化特征。

您还可以在使用 HTTP REST API 请求时优化性能。当使用 REST API 时，您应遵循属于 SDK 一部分的相同最佳实践。对于慢速连接允许超时和重试，并使用多个连接以允许并行提取对象数据。有关使用 REST API 的信息，请参阅 [Amazon Simple Storage Service API 参考](https://docs.aws.amazon.com/AmazonS3/latest/API/)。

# Amazon S3 的性能设计规律
<a name="optimizing-performance-design-patterns"></a>

当设计应用程序以从 Amazon S3 上传和检索对象时，使用我们的最佳实践设计模式，以实现应用程序的最佳性能。我们还提供 [Amazon S3 的性能准则 ](optimizing-performance-guidelines.md)，供您在规划您的应用程序架构时考虑。

要优化性能，您可以使用以下设计模式。

**Topics**
+ [对频繁访问的内容使用缓存](#optimizing-performance-caching)
+ [延迟敏感型应用程序的超时和重试](#optimizing-performance-timeouts-retries)
+ [水平扩缩和请求并行化以实现高吞吐量](#optimizing-performance-parallelization)
+ [使用 Amazon S3 Transfer Acceleration 加快地理位置分散的数据传输速度](#optimizing-performance-acceleration)
+ [针对高请求率工作负载进行优化](#optimizing-performance-high-request-rate)

## 对频繁访问的内容使用缓存
<a name="optimizing-performance-caching"></a>

许多在 Amazon S3 中存储数据的应用程序会提供用户反复请求的数据的一个“工作集”。如果工作负载针对一组常用对象发送重复的 GET 请求，则可以使用 [Amazon CloudFront](https://docs.aws.amazon.com/cloudfront/index.html)、[Amazon ElastiCache](https://docs.aws.amazon.com/elasticache/index.html) 或 [AWS Elemental MediaStore](https://docs.aws.amazon.com/mediastore/index.html) 等缓存来优化性能。成功地采用缓存可能导致低延迟和较高的数据传输速率。使用缓存的应用程序还会向 Amazon S3 发送少量的直接请求，这可帮助降低请求成本。

Amazon CloudFront 是一个快速内容交付网络 (CDN)，它透明地在一大组地理位置分散的节点 (PoP) 中缓存 Amazon S3 中的数据。当可能从多个区域或通过 Internet 访问对象时，CloudFront 允许在访问对象的用户附近缓存数据。这样就可以实现常见 Amazon S3 内容的高性能交付。有关 CloudFront 的更多信息，请参阅 [Amazon CloudFront 开发人员指南](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/)。

Amazon ElastiCache 是一个托管的内存中缓存。通过 ElastiCache，您可以预配置在内存中缓存对象的 Amazon EC2 实例。这种缓存会导致 GET 延迟下降若干个数量级，并显著增加下载吞吐量。要使用 ElastiCache，请修改应用程序逻辑，以便用热门对象填充缓存和检查缓存中的热门对象，然后从 Amazon S3 中请求它们。有关使用 ElastiCache 提高 Amazon S3 GET 性能的示例，请参阅博客文章[使用 Amazon ElastiCache for Redis 增强 Amazon S3](https://aws.amazon.com/blogs/storage/turbocharge-amazon-s3-with-amazon-elasticache-for-redis/)。

AWS Elemental MediaStore 是一个专为 Amazon S3 中的视频工作流和媒体交付构建的缓存和内容分配系统。MediaStore 提供专用于视频的端到端存储 API，推荐用于性能敏感型视频工作负载。有关 MediaStore 的更多信息，请参阅 [AWS Elemental MediaStore 用户指南](https://docs.aws.amazon.com/mediastore/latest/ug/)。

## 延迟敏感型应用程序的超时和重试
<a name="optimizing-performance-timeouts-retries"></a>

在某些情况下，应用程序会收到来自 Amazon S3 的响应，指示需要重试。Amazon S3 将存储桶和对象名称映射到与其关联的对象数据。如果应用程序生成高的请求率（通常针对少量对象持续超过每秒 5,000 个请求的速率），则它可能会收到 HTTP 503 *速度下降* 响应。如果出现这些错误，每个 AWS SDK 都会使用指数退避来实现自动重试逻辑。如果您不使用 AWS SDK，则应在收到 HTTP 503 错误时实施重试逻辑。有关回退技术的信息，请参阅《AWS SDK 和工具参考指南》**中的 [Retry behavior](https://docs.aws.amazon.com/sdkref/latest/guide/feature-retry-behavior.html)。

Amazon S3 自动扩展以应对持续的新请求速率，同时动态地优化性能。尽管 Amazon S3 在内部针对新的请求速率进行优化，但您将临时收到 HTTP 503 请求响应，直至优化完成。当 Amazon S3 在内部针对新的请求速率优化性能后，通常无需重试就能正常应对所有请求。

对于延迟密集型应用程序，Amazon S3 建议跟踪和主动重试较慢的操作。当重试请求时，我们建议您使用到 Amazon S3 的新连接并执行全新 DNS 查找。

当您发出大型可变大小的请求（例如，超过 128 MB）时，我们建议跟踪所实现的吞吐量并重试最慢 5% 的请求。当您发出较小的请求（例如，小于 512 KB）时，其中，延迟时间中值通常处于数十毫秒的范围内，好的指导原则是在 2 秒后重试 GET 或 PUT 操作。如果需要更多重试，则最佳实践是退避。例如，我们建议您在 2 秒后发出一次重试，然后 4 秒后再发出一次重试。

如果应用程序对 Amazon S3 发出固定大小的请求，则应预期对于其中每个请求获得更一致的响应时间。在这种情况下，一个简单的策略是确定最慢的 1% 的请求并重试这些请求。甚至一次重试也会频繁、有效地减少延迟。

如果您使用 AWS Key Management Service（AWS KMS）进行服务器端加密，请参阅《AWS Key Management Service 开发人员指南》**中的[配额](https://docs.aws.amazon.com/kms/latest/developerguide/limits.html)，以了解有关您的使用案例支持的请求速率的信息。

## 水平扩缩和请求并行化以实现高吞吐量
<a name="optimizing-performance-parallelization"></a>

Amazon S3 是一个非常大的分布式系统。为了帮助您利用其规模，我们建议您将并行请求横向扩展到 Amazon S3 服务端点。除了在 Amazon S3 中分布请求之外，这种类型的扩展方法还有助于将负载分布到整个网络中的多个路径。

对于高吞吐量传输，Amazon S3 建议使用并行利用多个连接来 GET 或 PUT 数据的应用程序。例如，AWS Java SDK 中的 [Amazon S3 Transfer Manager](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/transfer-manager.html) 支持上述功能，大多数其他 AWS SDK 也提供类似的构造。对于某些应用程序，您可以实现并行连接，具体方法为：在不同的应用程序线程或不同的应用程序实例中并行启动多个连接。要采取的最佳方法取决于应用程序以及您访问的对象的结构。

您可以使用 AWS SDK 直接发出 GET 和 PUT 请求，而不是利用 AWS SDK 中的传输管理。这种方法让您可以更直接地调整工作负载，同时仍受益于软件工具包支持重试和处理任何可能发生的 HTTP 503 响应。一般而言，当您从 Amazon S3 下载大型对象时，建议您发出并行请求，以最大限度地提高网络吞吐量并优化下载性能。为此，您可以请求对象的特定字节范围或同时下载分段对象的各个分段。这种并行下载方法有助于充分利用网络接口卡（NIC）的容量。对于使用分段上传方法上传的对象，建议使用相同的分段大小下载它们，或者将请求与原始分段边界对齐，以获得最佳性能。与对完整对象发出单个请求相比，这种并发下载方法可提供更高的聚合吞吐量。

当您调整并行发出的请求数量时，衡量性能至关重要。我们建议一次只用一个请求为起点。衡量所实现的网络带宽以及应用程序用于处理数据的其他资源的使用情况。然后，您可以确定瓶颈资源（也即使用率最高的资源），进而确定可能有用的请求数。例如，如果一次处理一个请求会导致 CPU 利用率达到 25%，则建议可以容纳多达四个并行请求。衡量是必不可少的，随着请求速率增加，务必确认资源使用情况。

如果应用程序使用 REST API 直接向 Amazon S3 发出请求，我们建议您使用 HTTP 连接池，并对一系列请求重用每个连接。通过避免逐个请求连接设置，可消除对每个连接执行 TCP 慢速启动和安全套接字层 (SSL) 握手的需要。有关使用 REST API 的信息，请参阅 [Amazon Simple Storage Service API 参考](https://docs.aws.amazon.com/AmazonS3/latest/API/)。

最后，务必注意 DNS 并仔细检查请求正在分散到广泛的 Amazon S3 IP 地址池。对于 Amazon S3 的 DNS 查询会循环经过一个很大的 IP 端点列表。但是，缓存解析程序或重用单一 IP 地址的应用程序代码不会受益于地址多样性和由此产生的负载平衡。网络实用工具（如 `netstat` 命令行工具）可以显示用来与 Amazon S3 通信的 IP 地址，并且我们提供要使用的 DNS 配置的准则。有关这些准则的更多信息，请参阅《Amazon S3 API 参考》**中的 [Making requests](https://docs.aws.amazon.com/AmazonS3/latest/API/MakingRequests.html)。

## 使用 Amazon S3 Transfer Acceleration 加快地理位置分散的数据传输速度
<a name="optimizing-performance-acceleration"></a>

[使用 Amazon S3 Transfer Acceleration 配置快速、安全的文件传输](transfer-acceleration.md) 通过使用 Amazon S3，有效地将由于全球分散的客户端与区域性应用程序之间的地理距离所导致的延迟降至最小甚至消除。Transfer Acceleration 使用 CloudFront 中的全球分布式边缘站点进行数据传输。AWS 边缘网络在超过 50 个站点具有节点。目前，它用于通过 CloudFront 分布内容，并向针对 [Amazon Route 53](https://docs.aws.amazon.com/route53/index.html) 发出的 DNS 查询提供快速响应。

边缘网络还有助于加速进出 Amazon S3 的数据传输。它对具有以下特点的应用程序是理想之选：跨大洲或在大洲之间传输数据、具有快速 Internet 连接、使用大型对象，或具有大量要上传的内容。当数据到达某个边缘站点时，数据会被经过优化的网络路径路由至 Amazon S3。通常，您与 Amazon S3 区域之间的距离越远，使用 Transfer Acceleration 可预期获得的速度改进就越大。

您可以对新的或现有的存储桶设置 Transfer Acceleration。您可以通过单独的 Amazon S3 Transfer Acceleration 端点来使用 AWS 边缘站点。测试 Transfer Acceleration 是否有助于提高客户端请求性能的最佳方法是使用 [Amazon S3 Transfer Acceleration 速度比较工具](https://s3-accelerate-speedtest.s3-accelerate.amazonaws.com/en/accelerate-speed-comparsion.html)。网络配置和条件随时间或站点不同而可能发生变化。因此，我们只对 Amazon S3 Transfer Acceleration 可能会改进上传性能的传输向您收费。有关将 Transfer Acceleration 与不同的 AWS SDK 结合使用的信息，请参阅 [启用和使用 S3 Transfer Acceleration](transfer-acceleration-examples.md)。

## 针对高请求率工作负载进行优化
<a name="optimizing-performance-high-request-rate"></a>

对 Amazon S3 生成高请求率的应用程序需要特定的设计模式才能实现最佳性能。当应用程序对于每个前缀每秒一致地生成超过 3500 个 PUT/COPY/POST/DELETE 请求或 5500 个 GET/HEAD 请求时，您应该实施策略来分配请求并处理扩展行为。

Amazon S3 会自动扩展以适应更高的请求率，但这种扩展是逐渐发生的。在扩展过程中，您可能会收到 HTTP 503（减速）响应。这些响应是临时性的，表明 Amazon S3 正在针对新的请求模式优化其内部系统。扩展完成后，请求就可以将在不受节流的情况下得到满足。

要优化高请求率工作负载的性能，请考虑以下策略：
+ **跨多个前缀分配请求**：使用随机化或顺序前缀模式将请求分散到多个分区中。例如，使用随机化前缀（例如 `a1b2/log-2024-01-01.txt`），而不使用顺序对象名称（如 `log-2024-01-01.txt`）。这有助于 Amazon S3 更有效地分配负载。
+ **对 503 错误实施指数回退**：收到 HTTP 503 响应时，使用指数回退来实施重试逻辑。以短暂的延迟开始，然后逐渐增加重试之间的等待时间。AWS SDK 包含内置的重试逻辑来自动处理此事宜。
+ **监控请求模式**：使用 Amazon CloudWatch 指标来监控请求率和错误率。请特别注意 5xx 错误指标，这些指标可以指示应用程序何时接近或超过当前的扩展限制。
+ **逐步提高请求率**：当启动新的应用程序或显著提高请求率时，请随着时间推移逐渐增加流量，而不是立即跳至峰值速率。这使得 Amazon S3 能够主动扩展，并降低节流的可能性。
+ **使用多个连接**：将请求分配到多个 HTTP 连接，以最大限度地提高吞吐量并减少任何单个连接问题的影响。

对于需要一致高性能的应用程序，可以考虑使用 Amazon S3 Express One Zone 存储类，它专为需要个位数毫秒延迟的应用程序而设计，每秒可以支持数十万个请求。有关更多信息，请参阅 [S3 Express One Zone](directory-bucket-high-performance.md#s3-express-one-zone)。