如何为静态附件生成带指纹的 URL 并配置 Nginx 缓存 1 年?

解读

在国内生产环境中,CouchDB 常被当作“带同步能力的静态资源仓库”使用:移动端先把图片、JS、APK 等附件同步到本地,再离线运行。
面试官问“带指纹 URL + 1 年缓存”,本质考察三件事:

  1. 让 CouchDB 附件 URL 可感知内容变化(指纹),解决“同名文件更新后客户端仍用旧缓存”的痛点;
  2. 让 Nginx 在边缘节点强缓存 365 天,降低回源流量、提升全国访问速度;
  3. 整套方案不改 CouchDB 源码,靠官方已有机制组合完成,体现“用开源组件拼生产级架构”的能力。

知识点

  • CouchDB 附件存储模型_attachments 是文档内嵌对象,键=文件名,值含 content_typelengthdigest(SHA-1 十六进制)。
  • ETag 生成规则:CouchDB 默认把 digest 作为 ETag,回写给客户端;GET /db/doc/file.ext 时带 If-None-Match 即可 304。
  • rewrite 规则_design/rewrites 数组支持正则捕获与变量替换,可把 /static/* 映射到真实附件路径,并把 digest 前 8 位拼进 URL,形成指纹。
  • Nginx 缓存指令expires 365d;add_header Cache-Control "public, max-age=31536000, immutable"; 两者同时写,覆盖所有浏览器。
  • SRI(Subresource Integrity)补充:若前端用 integrity="sha256-...",指纹 URL 可天然对齐,提高安全分。
  • 国内 CDN 备案注意:若 Nginx 前置接阿里云/腾讯云 CDN,需把 Cache-Control透传给 CDN,否则 24 小时就会被强制回源。

答案

步骤一:设计文档里加 rewrite,把 digest 拼成路径

{
  "_id": "_design/static",
  "rewrites": [
    {
      "from": "/static/:digest/:name",
      "to": "../../../*",
      "query": {}
    }
  ]
}

步骤二:业务端生成带指纹的 URL
doc._attachments['logo.png'].digestsha1-2jmj7l5rSw0yVb/vlWAYkK/YBwk=,截前 8 位得 2jmj7l5r,拼成
https://cdn.example.com/db/_design/static/_rewrite/static/2jmj7l5r/logo.png
文件内容一旦变,digest 必变,URL 随之变,强制击穿缓存

步骤三:Nginx 配置(站点 conf)

location ~ ^/db/_design/static/_rewrite/static/ {
    proxy_pass http://couchdb_upstream;
    proxy_set_header Host $host;
    # 1 年强缓存
    expires 365d;
    add_header Cache-Control "public, max-age=31536000, immutable";
    # 去掉 Cookie,防止缓存键爆炸
    proxy_hide_header Set-Cookie;
}

步骤四:验证

  1. 第一次 curl -I 返回 200 + ETag:"2jmj7l5rSw0yVb/vlWAYkK/YBwk="
  2. 第二次带 If-None-Match 返回 304,证明 CouchDB 层正常;
  3. 关闭 CouchDB,仍能从 Nginx 缓存拿到 200X-Cache: HIT),TTL=31536000,达成 1 年缓存目标

拓展思考

  1. 多节点 digest 一致性:CouchDB 多主复制时,同一附件的 digest 全局一致,因此指纹 URL 在任意节点都相同,可做 GeoDNS 就近解析。
  2. SHA-1 冲突应对:国内等保 2.0 场景若要求 SHA-256,可在应用层计算后把前 16 位当指纹,rewrite 规则不变,仍兼容。
  3. 缓存失效应急:若发现恶意文件已扩散,可在 Nginx 加 map $request_uri $purge 逻辑,调用 proxy_cache_purge 模块按指纹批量清除,避免改文件名。
  4. 成本优化:华北/华东云主机出流量单价 0.8 元/GB,1 年缓存可把回源率压到 <2%,10 TB 附件年省 6 万元
  5. 面试加分项:提到“把 fingerprint 写入 Prometheus 指标”,可监控“旧指纹请求量”,量化缓存命中率,体现可观测性思维。