

# 管理内容保留在缓存中的时间长度（过期）
<a name="Expiration"></a>

您可控制文件在 CloudFront 转发另一请求到您的源之前留在 CloudFront 缓存中的时长。减少持续时间让您可提供动态内容。增加持续时间意味着您的用户将获得更好的性能，因为直接从边缘缓存提供文件的可能性更大。较长的持续时间还会减少源的负载。

通常，CloudFront 从边缘站点提供文件，直至超出您指定的缓存时长，直至文件过期。文件过期后，边缘站点下次收到对文件的请求时，CloudFront 会将请求转发到源，以确认缓存包含文件的最新版本。来自源的响应取决于文件是否已更改：
+ 如果 CloudFront 缓存已具有最新版本，则源将返回状态代码 `304 Not Modified`。
+ 如果 CloudFront 缓存没有最新版本，则源将返回 `200 OK` 状态代码和文件的最新版本。

如果边缘站点中的某个文件不常被请求，则 CloudFront 可能会移除该文件 – 在文件到期日之前删除文件，以便为最近常被请求的文件腾出空间。

我们建议通过更新分配的缓存策略来管理缓存持续时间。如果您选择不使用缓存策略，则默认 TTL（生存时间）为 24 小时，但您可以更新以下设置来覆盖默认值：
+ 要更改所有匹配相同路径模式的文件的缓存持续时间，可以更改缓存行为的**最小 TTL**、**最大 TTL** 和**默认 TTL** 的 CloudFront 设置。有关各个设置的信息，请参阅[最小 TTL](DownloadDistValuesCacheBehavior.md#DownloadDistValuesMinTTL)、[最大 TTL](DownloadDistValuesCacheBehavior.md#DownloadDistValuesMaxTTL) 和[默认 TTL](DownloadDistValuesCacheBehavior.md#DownloadDistValuesDefaultTTL)。
+ 要更改单个文件的缓存持续时间，您可以配置源以向文件中添加 `Cache-Control` 标头以及 `max-age` 或 `s-maxage` 指令或者添加 `Expires` 标头。有关更多信息，请参阅 [使用标头控制单独对象的缓存时间长度](#expiration-individual-objects)。

有关**最小 TTL**、**默认 TTL** 和**最大 TTL** 如何与 `max-age` 和 `s-maxage` 指令以及 `Expires` 标头字段交互的更多信息，请参阅[指定 CloudFront 缓存对象的时间长度](#ExpirationDownloadDist)。

您还可以控制在 CloudFront 将另一个请求转发到源以再次尝试获取请求的对象之前，在 CloudFront 缓存中保留错误（例如，`404 Not Found`）的时间。有关更多信息，请参阅 [CloudFront 如何处理来自源的 HTTP 4xx 和 5xx 状态代码](HTTPStatusCodes.md)。

**Topics**
+ [使用标头控制单独对象的缓存时间长度](#expiration-individual-objects)
+ [提供过时（过期）的内容](#stale-content)
+ [指定 CloudFront 缓存对象的时间长度](#ExpirationDownloadDist)
+ [使用 Amazon S3 控制台向对象添加标头](#ExpirationAddingHeadersInS3)

## 使用标头控制单独对象的缓存时间长度
<a name="expiration-individual-objects"></a>

您可以使用 `Cache-Control` 和 `Expires` 标头控制对象保留在缓存中的时间长度。**最小 TTL**、**默认 TTL** 和**最大 TTL** 的设置也会影响缓存时间长度，不过此处只简要说明标头对缓存时间长度的影响：
+ `Cache-Control max-age` 指令让您指定希望对象在 CloudFront 再次从源服务器获取对象之前保留在缓存中的时长（以秒为单位）。CloudFront 支持的最短到期时间为 0 秒。最大值为 100 年。采用以下格式指定值：

  `Cache-Control: max-age=`*秒*

  例如，以下指令告诉 CloudFront 在缓存中将相关对象保留 3600 秒（一小时）：

  `Cache-Control: max-age=3600`

  如果您希望对象在 CloudFront 边缘缓存中保留的时间不同于在浏览器缓存中的保留时间，可以将 `Cache-Control max-age` 和 `Cache-Control s-maxage` 指令一起使用。有关更多信息，请参阅 [指定 CloudFront 缓存对象的时间长度](#ExpirationDownloadDist)。
+ `Expires`标头字段让您使用 [RFC 2616, Hypertext Transfer Protocol -- HTTP/1.1 Section 3.3.1, Full Date](https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3.1) 中指定的格式指定过期日期和时间，例如：

  `Sat, 27 Jun 2015 23:59:59 GMT`

建议您使用 `Cache-Control max-age` 指令代替 `Expires` 标头字段，以控制对象缓存。如果您同时指定 `Cache-Control max-age` 和 `Expires` 的值，CloudFront 则只使用 `Cache-Control max-age` 的值。

有关更多信息，请参阅 [指定 CloudFront 缓存对象的时间长度](#ExpirationDownloadDist)。

您不能使用查看器的 `Cache-Control` 请求中的 HTTP `Pragma` 或 `GET` 标头字段来强制 CloudFront 返回到对象的源服务器。CloudFront 将忽略查看器请求中的这些标头字段。

有关 `Cache-Control` 和 `Expires` 标头字段的更多信息，请参阅*《RFC 2616，超文本传输协议 – HTTP/1.1》*中以下章节：
+ [第 14.9 节：缓存控制](https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9)
+ [第 14.21 节：过期](https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.21)

## 提供过时（过期）的内容
<a name="stale-content"></a>

CloudFront 支持 `Stale-While-Revalidate` 和 `Stale-If-Error` 缓存控制指令。可以使用这些指令来指定过时内容可供查看器使用多长时间。

**Topics**
+ [`Stale-While-Revalidate`](#stale-while-revalidate)
+ [`Stale-If-Error`](#stale-if-error-only)
+ [同时使用两个指令](#use-both-stale-directives)

### `Stale-While-Revalidate`
<a name="stale-while-revalidate"></a>

此指令可让 CloudFront 从缓存中提供过时内容，同时 CloudFront 从源异步获取新版本。这样可以缩短延迟，因为查看器无需等待后台获取，即可立即收到来自边缘站点的响应。新内容将在后台加载，以供将来的请求使用。

**Example 示例：`Stale-While-Revalidate`**  
当您将 `Cache-Control` 标头设置为使用这些指令时，CloudFront 会执行以下操作。  

```
Cache-Control: max-age=3600, stale-while-revalidate=600
```

1. CloudFront 会将响应缓存一小时 (`max-age=3600`)。

1. 如果在此持续时间之后发出请求，CloudFront 将提供过时的内容，同时向源发送请求以重新验证和刷新缓存的内容。

1. 在重新验证内容期间，CloudFront 最多可提供 10 分钟 (`stale-while-revalidate=600`) 的过时内容。

**注意**  
CloudFront 提供过时内容的时间最长可达 `stale-while-revalidate` 指令的值或 CloudFront [最大 TTL](DownloadDistValuesCacheBehavior.md#DownloadDistValuesMaxTTL) 的值，以较小者为准。在最大 TTL 持续时间之后，无论 `stale-while-revalidate` 值如何，都无法从边缘缓存中提供过时的对象。

### `Stale-If-Error`
<a name="stale-if-error-only"></a>

此指令可让 CloudFront 在源不可访问或源返回介于 500 和 600 之间的错误代码时从缓存中提供过时内容。这可确保查看器即使在源中断期间也可以访问内容。

**Example 示例：`Stale-If-Error`**  
当您将 `Cache-Control` 标头设置为使用这些指令时，CloudFront 会执行以下操作。  

```
Cache-Control: max-age=3600, stale-if-error=86400
```

1. CloudFront 会将响应缓存一个小时 (`max-age=3600`)。

1. 如果源在此持续时间后断开或返回错误，CloudFront 将在长达 24 小时 (`stale-if-error=86400`) 内继续提供过时内容。

1. 如果您配置了自定义错误响应，则当在指定的 `stale-if-error` 持续时间内遇到错误时，CloudFront 将首先尝试提供过时内容。如果过时内容不可用，CloudFront 将提供您为相应错误状态代码配置的自定义错误响应。有关更多信息，请参阅 [生成自定义错误响应](GeneratingCustomErrorResponses.md)。

**备注**  
CloudFront 提供过时内容的时间最长可达 `stale-if-error` 指令的值或 CloudFront [最大 TTL](DownloadDistValuesCacheBehavior.md#DownloadDistValuesMaxTTL) 的值，以较小者为准。在最大 TTL 持续时间之后，无论 `stale-if-error` 值如何，都无法从边缘缓存中提供过时的对象。
如果您没有配置 `stale-if-error` 或自定义错误响应，CloudFront 将返回过时对象，或将错误响应转发回给查看器，具体取决于所请求的对象是否在边缘缓存中。有关更多信息，请参阅 [如果您尚未配置自定义错误页面，CloudFront​ 如何处理错误](HTTPStatusCodes.md#HTTPStatusCodes-no-custom-error-pages)。

### 同时使用两个指令
<a name="use-both-stale-directives"></a>

`stale-while-revalidate` 和 `stale-if-error` 都是独立的缓存控制指令，您可以将它们一起使用来减少延迟，并为源添加缓冲区以进行响应或恢复。

**Example 示例：同时使用两个指令**  
当您将 `Cache-Control` 标头设置为使用以下指令时，CloudFront 会执行以下操作。  

```
Cache-Control: max-age=3600, stale-while-revalidate=600, stale-if-error=86400
```

1. CloudFront 会将响应缓存一个小时 (`max-age=3600`)。

1. 如果在此持续时间之后发出请求，CloudFront 将在重新验证内容期间提供最长 10 分钟 (`stale-while-revalidate=600`) 的过时内容。

1. 如果在 CloudFront 尝试重新验证内容时原始服务器返回错误，CloudFront 将继续在最长 24 小时 (`stale-if-error=86400`) 内提供过时内容。

缓存是性能和新鲜度之间的平衡。使用 `stale-while-revalidate` 和 `stale-if-error` 之类的指令可以增强性能和用户体验，但要确保配置与您所需的内容新鲜度相一致。过时内容指令最适合需要刷新内容但并非必须具有最新版本的使用案例。此外，如果您的内容没有更改或极少更改，`stale-while-revalidate` 可能会增加不必要的网络请求。相反，可以考虑设置较长的缓存持续时间。

## 指定 CloudFront 缓存对象的时间长度
<a name="ExpirationDownloadDist"></a>

要控制 CloudFront 在将另一个请求发送到源之前在缓存中保留对象的时长，您可以：
+ 设置 CloudFront 分配的缓存行为中的最小、最大和原定设置 TTL 值。您可以在附加到缓存行为的[缓存策略](controlling-the-cache-key.md)中设置这些值（推荐），或在原有缓存设置中进行设置。
+ 将 `Cache-Control` 或 `Expires` 标头包含在来自源的响应中。这些标头还有助于确定浏览器在浏览器缓存中保留对象的时间长度，超过该时间长度后才会将另一个请求发送到 CloudFront。

下表说明了从源发送的 `Cache-Control` 和 `Expires` 标头如何与缓存行为中的 TTL 设置配合使用，从而影响缓存的。


****  

| 源标头 | 最小 TTL = 0 | 最小 TTL > 0 | 
| --- | --- | --- | 
|  **源将 `Cache-Control: max-age` 指令添加到对象**  |  **CloudFront 缓存** CloudFront 缓存对象的时间长度为 `Cache-Control: max-age` 指令或 CloudFront 最长 TTL 的值（取二者中的较小值）。 **浏览器缓存** 浏览器缓存对象的时间长度为 `Cache-Control: max-age` 指令的值。  |  **CloudFront 缓存** CloudFront 缓存取决于 CloudFront 最短 TTL 和最长 TTL 的值以及 `Cache-Control max-age` 指令： [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/AmazonCloudFront/latest/DeveloperGuide/Expiration.html) **浏览器缓存** 浏览器缓存对象的时间长度为 `Cache-Control: max-age` 指令的值。  | 
|  **源不会将 `Cache-Control: max-age` 指令添加到对象**  |  **CloudFront 缓存** CloudFront 缓存对象的时间长度为 CloudFront 默认 TTL 值。 **浏览器缓存** 视浏览器而定。  |  **CloudFront 缓存** CloudFront 缓存对象的时间长度为 CloudFront 最小 TTL 或默认 TTL（以较大的值为准）。 **浏览器缓存** 视浏览器而定。  | 
|  **源将 `Cache-Control: max-age` 和 `Cache-Control: s-maxage` 指令添加到对象**  |  **CloudFront 缓存** CloudFront 缓存对象的时间长度为 `Cache-Control: s-maxage` 指令或 CloudFront 最长 TTL 的值（取二者中的较小值）。 **浏览器缓存** 浏览器缓存对象的时间长度为 `Cache-Control max-age` 指令的值。  |  **CloudFront 缓存** CloudFront 缓存取决于 CloudFront 最短 TTL 和最长 TTL 的值以及 `Cache-Control: s-maxage` 指令： [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/AmazonCloudFront/latest/DeveloperGuide/Expiration.html) **浏览器缓存** 浏览器缓存对象的时间长度为 `Cache-Control: max-age` 指令的值。  | 
|  **源将 `Expires` 标头添加到对象**  |  **CloudFront 缓存** CloudFront 缓存对象，直至 `Expires` 标头中的日期或 CloudFront 最长 TTL 的值，以先到者为准。 **浏览器缓存** 浏览器缓存对象，直至 `Expires` 标头中的日期。  |  **CloudFront 缓存** CloudFront 缓存取决于 CloudFront 最短 TTL 和最长 TTL 以及 `Expires` 标头的值： [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_cn/AmazonCloudFront/latest/DeveloperGuide/Expiration.html) **浏览器缓存** 浏览器缓存对象，直至 `Expires` 标头中的日期和时间。  | 
|  **源将 `Cache-Control: no-cache`、`no-store` 和/或 `private` 指令添加到对象**  |  CloudFront 和浏览器以标头为准。  |  **CloudFront 缓存** CloudFront 缓存对象的时间长度为 CloudFront 最短 TTL 值。[请参阅此表下面的警告](#stale-if-error)。 **浏览器缓存** 浏览器以标头为准。  | 

**警告**  
如果您的最小 TTL 大于 0，CloudFront 将使用缓存策略的最小 TTL，即使源标头中存在 `Cache-Control: no-cache`、`no-store` 和/或 `private` 指令。  
如果源可以访问，CloudFront 会从源获取对象并将其返回给查看器。
如果源无法访问并且最小*或* 最大 TTL 值大于 0，CloudFront 将提供其先前从源获取的对象。
为了避免该行为，请将 `Cache-Control: stale-if-error=0` 指令包含在从源返回的对象中。这样一来，如果源无法访问，以后 CloudFront 就会返回错误消息，作为对请求的响应，而不是返回其先前从源获取的对象。
当源标头包含 `Cache-Control: no-cache`、`no-store` 和/或 `private` 指令时，CloudFront 不会缓存来自 S3 来源的 HTTP 501 状态代码（未实现）。这是 S3 来源的默认行为，即使[最小 TTL](DownloadDistValuesCacheBehavior.md#DownloadDistValuesMinTTL) 设置大于 0 也是如此。

有关如何使用 CloudFront 控制台更改分配的设置的信息，请参阅[更新分配](HowToUpdateDistribution.md)。有关如何使用 CloudFront API 更改分配的设置的信息，请参阅 [UpdateDistribution](https://docs.aws.amazon.com/cloudfront/latest/APIReference/API_UpdateDistribution.html)。

## 使用 Amazon S3 控制台向对象添加标头
<a name="ExpirationAddingHeadersInS3"></a>

可以将 `Cache-Control` 或 `Expires` 标头字段添加到 Amazon S3 对象中。为此，请修改对象的元数据字段。

**向 Amazon S3 对象添加 `Cache-Control` 或 `Expires` 标头字段**

1. 按照《Amazon S3 用户指南》**中[在 Amazon S3 控制台中编辑对象元数据](https://docs.aws.amazon.com/AmazonS3/latest/userguide/add-object-metadata.html)主题的**替换系统定义的元数据**部分中的过程进行操作。

1. 对于**键**，选择要添加的标头的名称（**Cache-Control** 或 **Expires**）。

1. 对于**值**，输入标头值。例如，对于 `Cache-Control` 标头，您可以输入 `max-age=86400`。对于 `Expires`，您可以输入到期日期和时间，如 `Wed, 30 Jun 2021 09:28:00 GMT`。

1. 按照此过程的剩余部分操作，以保存元数据更改。