Nginx 不提供 etag 指令,也不能通过配置直接生成或控制 ETag 值;其 ETag 由系统在满足静态文件、sendfile 开启、未启用 gzip 等条件下,基于文件 mtime 和 size 自动生成弱校验值。

Nginx 本身不提供 etag 指令,也**不能通过配置指令直接生成或控制 ETag 值**。ETag 是由 Nginx 在特定条件下自动计算并添加的响应头,其行为取决于文件类型、是否启用缓存模块、是否开启 sendfile、以及是否启用了 gzip 等因素。所谓“利用 ETag 指令优化”属于常见误解——Nginx 没有 etag on/off 这样的配置项。
ETag 在 Nginx 中是如何工作的
Nginx 默认在以下条件下为静态文件(如图片)自动发送 ETag 响应头:
- 请求的是真实存在的静态文件(非 proxy_pass 或动态后端)
- 启用了
sendfile on(默认开启) - 未启用
gzip或gzip_vary导致内容编码不稳定(否则 ETag 会被禁用) - 文件未被子请求(subrequest)或第三方模块修改原始响应体
此时 Nginx 使用文件的 最后修改时间(mtime)和大小(size) 组合成弱校验 ETag,格式类似:W/"12345-67890abc"(十六进制 size + 十六进制 mtime)。它不基于内容哈希(如 MD5),因此无法检测到相同内容但不同文件名/路径的复用,也不抗篡改。
为什么对图片服务器来说 ETag 效果有限
图片类资源通常具备如下特点,导致 ETag 的实际收益较低:
-
更新频率低但 URL 易变:CDN 或构建工具常通过文件哈希重命名(如
logo.a1b2c3.png),文件内容不变时 URL 已不同,浏览器不会发起条件请求,ETag 完全不触发 -
强缓存优先级更高:配合
Cache-Control: public, max-age=31536000,浏览器直接复用本地副本,根本不发请求,ETag 无用武之地 - ETag 不节省带宽,只节省传输:304 响应仍需一次 TCP 往返和 HTTP 头开销;而强缓存连这个都省了
- gzip 启用时 ETag 被自动禁用:因压缩结果依赖客户端 Accept-Encoding,ETag 失去一致性,Nginx 主动移除该头
真正有效的图片服务优化策略
与其纠结 ETag,不如落实以下更可控、效果更明显的做法:
-
强制启用强缓存:在
location ~* \.(jpg|jpeg|png|gif|webp|svg)$块中设置expires 1y;和add_header Cache-Control "public, immutable";(immutable 可避免浏览器在 max-age 内发验证请求) -
统一关闭 ETag(可选):若你确认不需要条件请求,且使用 CDN,可用
etag off;—— 注意:这是 Nginx 1.7.3+ 支持的合法指令,用于显式禁用 ETag 输出,减少响应头体积 -
确保静态文件走 sendfile:确认未被
proxy_set_header、add_before_body等破坏零拷贝路径,避免触发内存读取进而丢失 ETag -
结合版本化 URL 或内容哈希:构建阶段生成
icon_v2.3e8d1f.png,内容变更则 URL 变,彻底规避缓存失效问题
验证 ETag 是否生效
使用 curl 检查响应头:
curl -I https://your.site/logo.png
若返回中含 ETag: 且后续请求携带 If-None-Match 并收到 304 Not Modified,说明 ETag 工作正常。但请记住:304 不代表性能最优,它只是“比 200 好一点”的折中方案。










