了解缓存键 - Amazon CloudFront

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

了解缓存键

缓存键决定观看者对 CloudFront 边缘位置的请求是否会导致缓存命中。缓存键是缓存中对象的唯一标识符。缓存中的每个对象都有一个唯一的缓存键。

如果查看器请求生成与先前请求相同的缓存键,并且该缓存键的对象位于边缘站点的缓存中且有效,则会发生缓存命中。当出现缓存命中时,请求的对象将从 CloudFront 边缘位置提供给查看者,这具有以下好处:

  • 减少了源服务器上的负载

  • 缩短了查看器的延迟

缓存命中率越高(当查看器请求比例较高时,会发生缓存命中),网站或应用程序的性能就越佳。提高缓存命中率的一种方法是仅在缓存键中包含最少的必要值。有关更多信息,请参阅以下部分。

您可以使用缓存策略修改缓存键中的值(URL 查询字符串、HTTP 标头和 Cookie)。(也可以使用 Lambda@Edge 函数修改缓存键。) 在修改缓存键之前,请务必了解应用程序的设计方式以及它何时以及如何根据查看器请求的特征提供不同的响应。当查看器请求中的某个值确定源返回的响应时,您应在缓存键中包含该值。但是,如果您在缓存键中包含的值不会影响源返回的响应,则可能最终会缓存重复的对象。

默认缓存键

默认情况下, CloudFront 分配的缓存密钥包含以下信息:

  • CloudFront 分配的域名(例如 d111111abcdef8.cloudfront.net)

  • 请求的对象的 URL 路径(例如 /content/stories/example-story.html

注意

OPTIONS 方法包含在 OPTIONS 请求的缓存键中。这意味着 OPTIONS 请求的响应将与 GETHEAD 请求的响应单独缓存。

默认情况下,查看器请求中的其他值不会包含在缓存键中。请考虑来自 Web 浏览器的以下 HTTP 请求。

GET /content/stories/example-story.html?ref=0123abc&split-pages=false HTTP/1.1 Host: d111111abcdef8.cloudfront.net User-Agent: Mozilla/5.0 Gecko/20100101 Firefox/68.0 Accept: text/html,*/* Accept-Language: en-US,en Cookie: session_id=01234abcd Referer: https://news.example.com/

当像这个例子这样的查看者请求进入 CloudFront 边缘位置时, CloudFront 使用缓存密钥来确定是否有缓存命中。默认情况下,缓存键中仅包含请求的以下组件:/content/stories/example-story.htmld111111abcdef8.cloudfront.net。如果请求的对象不在缓存中(缓存失败),则 CloudFront 向源发送请求以获取该对象。获取对象后,将其 CloudFront 返回给查看者并将其存储在边缘位置的缓存中。

当 CloudFront 收到由缓存密钥确定的对同一对象的另一个请求时,会立即将缓存的对象 CloudFront 提供给查看者,而无需向源发送请求。例如,请考虑以下 HTTP 请求,该请求在上一个请求之后到达。

GET /content/stories/example-story.html?ref=xyz987&split-pages=true HTTP/1.1 Host: d111111abcdef8.cloudfront.net User-Agent: Mozilla/5.0 AppleWebKit/537.36 Chrome/83.0.4103.116 Accept: text/html,*/* Accept-Language: en-US,en Cookie: session_id=wxyz9876 Referer: https://rss.news.example.net/

虽然该请求与上一个请求都对应于相同的对象,但它与上一个请求不同。它具有不同的 URL 查询字符串、User-AgentReferer 标头,以及不同的 session_id Cookie。但默认情况下,所有这些值都不是缓存键的一部分,因此第二个请求会导致发生缓存命中。

自定义缓存键

在某些情况下,即使这样做可能会导致更少的缓存命中,您仍可能希望在缓存键中包含更多信息。您可以使用缓存策略指定要包含在缓存键中的内容。

例如,如果您的源服务器使用查看器请求中的 Accept-Language HTTP 标头来根据查看器的语言返回不同的内容,则您可能希望在缓存键中包含此标头。执行此操作时, CloudFront 使用此标头来确定缓存命中率,并将标头包含在源请求中(缓存未命中时 CloudFront 发送到源的请求)。

在缓存键中包含其他值的一个潜在后果是,由于查看器请求中 CloudFront可能发生变化,最终可能会缓存重复的对象。例如,查看器可能会为 Accept-Language 标头发送以下任意值:

  • en-US,en

  • en,en-US

  • en-US, en

  • en-US

所有这些不同的值都表明查看者的语言是英语,但是这种变化可能会 CloudFront 导致多次缓存同一个对象。这会减少缓存命中数并增加源请求的数量。您可以避免此重复情况,方法是不在缓存键中包含 Accept-Language 标头,而是将您的网站或应用程序配置为将不同的 URL 用于不同语言的内容(例如 /en-US/content/stories/example-story.html)。

对于要包含在缓存键中的任何给定值,您应确保了解查看器请求中可能会出现的不同变体的数量。对于某些请求值,将它们包含在缓存键中几乎没有意义。例如,User-Agent 标头可以有数千个唯一变体,因此通常不适合将它作为包含在缓存键中的候选项。也不适合将具有用户特定的值或会话特定的值并且在数千个(甚至数百万个)请求中唯一的 Cookie 作为包含在缓存键中的候选项。如果您确实在缓存键中包含这些值,则每个唯一变体都会导致缓存中存在对象的另一个副本。如果对象的这些副本都不是唯一的,或者如果您最终获得了大量略微不同的对象,而每个对象只获得少量的缓存命中,则可能需要考虑另一种方法。您可以从缓存键中排除这些高度可变的值,也可以将对象标记为不可缓存。

在自定义缓存键时,请保持谨慎。有时这样做是可取的,但可能会产生意想不到的后果,例如缓存重复的对象、降低缓存命中率以及增加源请求的数量。如果您的源网站或应用程序需要接收来自查看器请求的特定值以进行分析、遥测或实现其他目的,但这些值不会更改源返回的对象,请使用源请求策略在源请求中包含这些值,但 将它们包含在缓存键中。