为来源减轻更多负载
概览
使用 CloudFront 可提高缓存命中率(CHR),从而提高 Web 应用程序的性能并减轻来源的负载。CHR 是指从 CloudFront 缓存服务的 HTTP 请求占请求总数的比率。更低的延迟(例如收到最后一个字节的时间)能够让从 CloudFront 缓存服务的请求受益,这样就使 CHR 成为一个衡量来源减负程度和应用程序性能的良好指标。可以使用缓存命中率 CloudWatch 指标来监控 CloudFront 分发的 CHR。要提高 CHR,可以优化 CloudFront 中的缓存配置、启用 Origin Shield 以及优化应用程序行为。
延长缓存生存时间(TTL)
可以使用来源发送的 Cache-Control 标头控制对象在 CloudFront 中的缓存时长,此标头受到“缓存策略”中配置的“生存时间”设置的限制。延长 TTL 会对 CHR 产生积极的影响,因此建议:
- 为来源配置 Cache-Control 标头以便更好地控制 CloudFront 中的 TTL,并利用浏览器缓存。
- 将静态资产作为不可变对象进行缓存(例如 Cache-Control: max-age=31536000, immutable),并对它们的 URL 路径进行版本控制(例如 /static/app.1be87a.js)。
- 对对象实施 ETAG,以受益于向来源发出的有条件的 HTTP 请求。
- 对于更加动态的内容,例如 HTML,在进行缓存(高 TTL)与让应用程序容忍陈旧内容(低 TTL)之间取得适当的平衡。
优化缓存密钥设置
使用缓存策略的缓存密钥设置,决定 CloudFront 是否重复使用缓存的对象来处理 HTTP 请求。经过优化的缓存密钥设置将使唯一缓存密钥与唯一对象保持 1:1 的比例。考虑一个无论附加的查询参数如何(例如 /about.html?utm_medium=social)都提供同一个 /about.html 的 Web 应用程序。如果将缓存密钥配置为包含 utm_medium 查询参数,CloudFront 将使用两个不同的缓存密钥缓存不同的 URL(例如 /about.html?utm_medium=social 和 /about.html?utm_medium=email)。这样会导致对来源的两次缓存脱靶,尽管这两个请求都是针对来源上的同一个文件,但这不够理想。
要优化缓存密钥设置,第一项最佳实践是在缓存密钥请求中专门包含将使来源做出不同响应的属性。为了实现这一目的,建议:
- 为需要不同缓存密钥设置的对象配置单独的缓存行为。
- 如果查询参数、标头或 Cookie 将使来源做出不同的响应,则只包含实际响应的内容(例如 Cookie user_id 而不是所有 Cookie)。
- 使用 CloudFront 中的响应标头策略管理 CORS,而不是添加 CORS 标头(例如 Origin, Access-Control-Request-Method, Access-Control-Request-Headers)以缓存密钥并在来源级别管理 CORS。
- 使用经过签名的 URL、CloudFront Functions 或 Lambda@Edge 将访问控制任务转移到 CloudFront,而不是在缓存密钥中添加授权标头并在来源级别进行管理。
- 使用 CloudFront 中的来源请求策略将 HTTP 属性转发到来源,而不是将它们添加到缓存密钥中。
第二项最佳实践是在将请求属性添加到缓存密钥之前对其进行标准化,以减小它的可能值的基数,每个可能值都会得到一个唯一的缓存密钥。为了实现这一目的,建议:
- 当使用查询参数时,按相同顺序和大小写发送查询参数
- 利用 CloudFront 生成的标头(例如 Cloudfront-is-Mobile-Viewer)识别设备类型,而不是将 User-agent 标头添加到缓存密钥中。
- 利用 CloudFront Functions 应用高级标准化,例如:重新排序查询参数并将其小写;根据是否存在 Cookie 提供不同版本的网页,而不是将 Cookie 添加到缓存密钥中;当可以向一组国家/地区发送相同的响应时,减少因国家/地区而异的响应变化;当需要压缩时,进一步减小 Accept-Encoding 的基数,或者当使用多个 CloudFront 设备检测标头时,进一步减小这些标头的基数。
启用 Origin Shield
默认情况下,CloudFront 使用两个高级缓存层减少对来源的缓存脱靶次数:一个位于 PoP 级别的缓存层和另一个位于区域性边缘缓存(REC)级别的缓存层。名义上,CloudFront PoP 与全球 10 多个 REC 之一相关联。当一个请求导致在 PoP 级别发生缓存脱靶时,CloudFront 会检查相关 REC 的缓存以满足此请求,而且仅当此请求未缓存在该 REC 中时,CloudFront 才会将此请求转发到来源。为了保持高可用性,REC 相互隔离,因此不会共享它们的缓存。这样,当从世界各地的不同地点请求常用对象时,CloudFront 将从多个 REC 向来源发送多个针对同一批对象的请求。
![](https://d1.awsstatic.com/achrsouk/origin-offload-without-os.93172a77eda67b0aa12df5f6caf2ea4f85aea699.png)
为了减少转发到来源的请求数量,可以在 CloudFront 中启用 Origin Shield,这是 REC 与来源之间的第三个高级缓存层。REC 并不直接从来源请求对象,而是首先尝试满足来自 Origin Shield 缓存的请求。
![](https://d1.awsstatic.com/achrsouk/origin-offload-with-os.dce36e4c5c0f58c3fbc01532c54eb8903b435502.png)
优化应用程序行为
考虑可能对缓存命中率产生积极影响的应用程序级更改。示例包括:
- 减小应用程序服务的基数对象。当应用程序为同一个资产生成多个格式副本(例如为了适应不同的屏幕而使用不同大小的图像)时,可以考虑将这一数量限制为宽度和高度的可能值。
- 利用浏览器缓存。可以使用来源发送的 Cache-Control 标头实现这一目的。可以在 Cache-Control 标头中使用 max-age 和 s-maxage 指令,或者对浏览器使用 Cache-Control 标头并使用“缓存策略”控制 CloudFront TTL,以区分 CloudFront 与浏览器之间的 TTL。
- 在客户端中使用字节范围请求,以便只下载所需的内容。