AWS CloudFront部分图片仍回源请求问题咨询
兄弟,我来帮你拆解下这个问题——毕竟CloudFront的缓存逻辑看起来简单,但细节坑不少。结合你的场景(CloudFront转HTTPS、源站是HTTP的ELB、后端Nginx),我整理了几个最可能导致部分Hit、部分Miss的原因,你可以逐一排查:
1. 缓存键(Cache Key)不一样是重灾区
CloudFront默认的缓存键会包含请求URL、HTTP方法、Host头,还有所有查询字符串。举个例子:如果两张看起来一样的图片,一个请求带了?v=202401,另一个带了?v=202402,或者请求的Host头有细微差别(比如cdn.example.com和www.cdn.example.com),CloudFront会把它们当成完全不同的缓存对象,自然一个Hit一个Miss。
- 排查动作:对比Hit和Miss请求的完整URL,看看有没有不同的查询参数;去CloudFront控制台看缓存行为配置,要是不需要转发所有查询参数,就改成「转发白名单中的查询字符串」或者直接「不转发」,减少缓存键的差异。
2. 源站返回的缓存控制头不一致
如果Nginx给不同图片返回的Cache-Control头不一样,比如有些图片返回max-age=31536000(一年缓存),有些却返回no-cache或者max-age=0,CloudFront会严格遵循这些指令——后者根本不会被缓存,每次都得回源。
- 排查动作:用
curl分别请求Hit和Miss的图片(直接访问ELB的HTTP地址),看响应头里的Cache-Control、Expires字段。建议给所有图片资源统一配置合理的缓存规则,比如Nginx里加这段:
location ~* \.(png|jpg|jpeg|gif|webp)$ { expires 1y; add_header Cache-Control "public, immutable"; }
immutable可以告诉CloudFront,这个资源不会变,不用频繁回源验证。
3. 缓存行为配置有差异
要是你在CloudFront里配了多个缓存行为,不同路径的图片可能匹配了不同的规则。比如某个行为设置了「不缓存」或者TTL特别短,另一个行为正常缓存,那自然会出现差异。
- 排查动作:进CloudFront控制台看缓存行为的路径模式(Path Pattern),确认所有图片路径都匹配到了正确的、允许缓存的行为;同时检查该行为的「缓存策略」,确保TTL设置合理,没有勾选「禁用缓存」。
4. 不必要的请求头被转发了
如果你的缓存行为配置了转发Cookie或者Authorization头,而不同请求携带的这些头不一样,CloudFront会把它们当成不同的请求,生成不同的缓存键,导致Miss。图片资源一般根本不需要这些头,完全可以禁用转发。
- 排查动作:看缓存行为的「转发头」设置,确认只转发必要的头(比如Host),Cookie和Authorization选「不转发」或者「转发白名单」(除非你真的有特殊需求)。
5. 缓存的自然生命周期或淘汰
有些图片是首次被请求,那肯定是Miss;或者缓存已经过期(超过了你设置的TTL),CloudFront会回源拉新内容。另外,如果CloudFront的缓存空间不够,会用LRU(最近最少使用)算法淘汰旧缓存,导致某些很久没被访问的图片再次请求时Miss。
- 排查动作:看Miss请求的
Age响应头,如果Age=0,说明是首次请求;如果Age接近你设置的TTL值,就是缓存刚过期。要是有重要图片需要一直命中,可以用CloudFront的「Create Invalidation」功能手动预热缓存。
6. 源站响应有细微差异
如果同一图片的请求,ELB返回的响应内容有细微不同(比如ETag、Last-Modified头不一样),CloudFront会认为资源更新了,会重新缓存新的版本,之前的缓存就失效了,导致Miss。
- 排查动作:多次请求同一图片(直接访问ELB),检查响应的ETag、Last-Modified是否一致;建议让Nginx基于文件内容生成ETag,而不是文件修改时间,避免不必要的差异。
总结下,最快的排查方法就是先对比Hit和Miss请求的完整URL、请求头、响应头,找到它们的差异点,再对应上面的方向解决。
内容的提问来源于stack exchange,提问作者Jake He

