
Etag 是 Nginx 中实现 HTTP 缓存验证的核心机制,它不直接决定是否缓存,而是配合 If-None-Match 和 If-Match 请求头,让客户端和服务器协商资源是否“未变”——从而避免重复传输。
强 ETag:字节级一致才通过校验
强 ETag(以 "xxx" 形式表示,无前缀)要求资源内容的每一个字节完全相同。Nginx 默认为静态文件生成强 ETag(基于文件最后修改时间与大小组合的哈希值,如 "5d8a0e9f-2a4b")。当客户端发起带 If-None-Match: "xxx" 的请求时,Nginx 会重新计算当前资源的 ETag 并严格比对:
匹配成功 → 返回 304 Not Modified,不发响应体 任意字节变化(哪怕改一个空格)→ ETag 不同,返回 200 OK 和新内容 若响应中含 Cache-Control: no-cache 或 Pragma: no-cache,浏览器仍会发条件请求,强 ETag 依然生效
弱 ETag:语义等价即可通过校验
弱 ETag 以 W/"xxx" 开头(例如 W/"abc123"),表示“内容在语义上等价”,不要求字节完全一致。Nginx 本身 不原生生成弱 ETag,需手动配置或由上游应用(如 FastCGI、proxy_pass 后端)注入。常见适用场景:
HTML 页面经服务端动态渲染,但主体内容未变,仅时间戳/统计代码微调 API 响应中包含非关键字段(如 "updated_at": "2024-06-01T12:00:00Z" 随每次请求更新,但业务数据未变 使用 add_header ETag W/"$upstream_http_etag"; 转发后端弱 ETag,同时确保 if_modified_since off; 避免与 Last-Modified 冲突
Nginx 中控制 ETag 行为的关键配置
Etag 功能默认开启,但行为受多个指令影响,需协同调整:
etag on | off;:全局开关,off 会彻底移除 ETag 响应头(包括后端传来的) if_modified_since before | exact | off;:影响 If-Modified-Since 校验逻辑;设为 off 可避免与弱 ETag 混用时的校验冲突 静态文件 ETag 无法自定义算法,但可通过 add_header ETag ""; 清空并替换为自定义值(注意:需配合 expires 或 cache_control 确保缓存策略合理) 代理场景下,若上游已设 ETag,Nginx 默认透传;如需强制重算,需关闭 etag off; 并自行添加
调试与验证 ETag 是否生效
实际部署中需确认 ETag 是否按预期工作,推荐组合验证方式:
用 curl -I 查看响应头是否存在 ETag,并观察是否带 W/ 前缀 发起两次请求:首次记录 ETag 值,第二次加请求头 -H "If-None-Match: \"xxx\"",检查返回码是否为 304 修改文件内容后重复测试,强 ETag 应触发 200;若仍返回 304,说明 ETag 未更新或被缓存中间件覆盖 注意浏览器开发者工具 Network 面板中,Size 列显示 from disk cache 或 from memory cache 表示本地缓存命中,而 304 表示协商缓存生效

评论(0)