这个问题接近 stackoverflow/serverfault,所以请不要因为它在这里而责怪我 :)
我在 AWS 上托管了一个服务,nginx 背后有 node.js。我有一个 cloudfront 分发设置来处理以服务为源的请求(无需添加应用服务器即可增长)
亚马逊建议在设置云端分布时从转发的请求中过滤掉大多数标头,特别是 User-Agent,他们声称这可能会有很大差异,从而降低 CDN 设置的有效性。
这在大多数情况下都很有效,除了尝试在 Facebook 上分享页面时,在这种情况下我需要知道用户代理实际上是 Facebook(facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)) 能够返回自定义响应。
我将为 Facebook 共享创建一个特殊路径,以便在这种情况下使用自定义云端行为,但不幸的是我无法控制用户会做什么,因此共享的 URL 可能与“常规”服务器 URL 相同。
有什么建议吗?
答案1
User-Agent:
如果您需要了解某种情况的用户代理,那么除了在相关的 CloudFront 行为中将标头列入白名单之外,您几乎无能为力。
CloudFront 根据其发送的请求标头缓存响应,因此最终结果是,对于给定的请求,通过转发请求获得的缓存响应User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36
将不会被 CloudFront 视为可用于处理未来的请求,User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.85 Safari/537.36
即使从所有实际目的来看,它都是同一个浏览器。
当您将 CloudFront 配置为基于一个或多个标头进行缓存,并且标头具有多个可能值时,CloudFront 会将更多请求转发到同一对象的源服务器。这会降低性能并增加源服务器上的负载。如果您的源服务器无论给定标头的值如何都返回相同的对象,我们建议您不要将 CloudFront 配置为基于该标头进行缓存。
—http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/header-caching.html
短语“将 CloudFront 配置为基于一个或多个标头进行缓存”与将“白名单标头”转发到原点。
这就是只转发所需内容的原因——否则会损害您的缓存命中率,在这种情况下,由于User-Agent:
字符串的变化,这意味着您无法充分利用边缘缓存,源服务器处理的请求更多,源服务器和 CloudFront 之间使用的带宽更多……但实际上没有其他选择。CloudFront 不会对边缘缓存中的存储收取任何费用,因此唯一的成本差异将是其他因素中发现的任何差异。
短语“降低性能”(上文)并不意味着 CloudFront 变慢 - 它仅指由于可能的标头值的变化,任何特定请求成为缓存命中的可能性降低。
顺便说一句,在这方面,CloudFront 的行为是正确的,因为变化User-Agent:
可能意味着变化的响应,正如您确实指出的那样。
在您描述的情况下,明智地使用路径模式和多种缓存行为是充分利用 CDN 缓存的关键。建议只将User-Agent:
需要它的路径模式列入白名单,例如/images/*
(当然,这是我刚刚编造的路径)。同样的建议也适用于 Cookie 和查询字符串以及标头。对于不需要 Cookie 和/或查询字符串的路径模式,不要启用 Cookie 和/或查询字符串转发 - 否则,缓存的响应将仅提供给提供相同 Cookie 的用户或路径和查询字符串与缓存响应匹配的请求 - 因此,显然,在这种情况下不会有很多缓存命中。
答案2
现在可以使用原产地请求政策。
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/controlling-origin-requests.html
这样我们就可以将标头转发到源站,而无需考虑缓存目的。虽然可以根据需要微调策略,但有一个预定义的源站请求策略称为Managed-UserAgentRefererHeaders
,它使源站User-Agent
标头在源站(或源请求就此而言,Lambda@edge 函数)。