linux怎么配置nginx解决varnish缓存冲突 nginx代理架构详解

Varnish 和 Nginx 在同一台机器上共用 80 端口时,缓存行为会互相干扰——根本原因不是“谁先启动”,而是请求路径没被正确分流,导致 Nginx 直接回源或绕过 Varnish 缓存。

为什么 Nginx 反代 Varnish 后仍出现 X-Cache: MISS 或缓存失效

常见现象是:浏览器看到 X-Cache: MISS、Age: 0、Via: 1.1 nginx(而非 varnish),说明请求根本没进 Varnish。这不是 Varnish 配置问题,而是 Nginx 没把该请求转发给它。

典型错误配置:

Nginx 的 proxy_pass 指向后端应用(如 http://127.0.0.1:8080),跳过了 VarnishVarnish 监听在 127.0.0.1:6081,但 Nginx 的 proxy_pass 写成 http://localhost:6081(某些系统下解析慢或失败)没禁用 Nginx 自身的缓存(proxy_cache),和 Varnish 形成双重缓存逻辑冲突客户端直接访问 Nginx 的 80 端口,而 Nginx 对静态资源(.js、.css)做了 try_files 本地响应,根本没发请求出去

让 Nginx 正确代理到 Varnish 的关键配置项

核心原则:Nginx 做纯七层反向代理(不缓存、不重写、不拦截),把所有需缓存的流量无损转给 Varnish。

必须确认以下几点:

proxy_pass 必须明确指向 Varnish 监听地址,推荐用 http://127.0.0.1:6081(避免 DNS 解析开销)关闭 Nginx 自身缓存:proxy_cache off;,且确保没有全局 proxy_cache_path 生效透传原始 Host 和协议:proxy_set_header Host $host;、proxy_set_header X-Forwarded-Proto $scheme;禁用 Nginx 对静态文件的本地服务逻辑(删掉或注释掉 location ~ \.(js|css|png|jpg)$ { try_files … } 这类块)若需支持 HTTPS,Nginx 终止 SSL 后,用 proxy_set_header X-Forwarded-Proto https; 告知 Varnish,否则 Varnish 可能因判断非 HTTP 而跳过缓存

Varnish 的 vcl_recv 中必须处理 Nginx 透传的头信息

Varnish 默认只缓存 GET 和 HEAD 请求,且对带 Cookie 或 Authorization 的请求默认 bypass。但 Nginx 透传过来的请求如果含这些头,Varnish 会直接 pass,造成全量 MISS。

在 /etc/varnish/default.vcl 的 vcl_recv 中至少加这几行:

sub vcl_recv { if (req.method == "PURGE") { return (purge); } if (req.url ~ "\.(js|css|png|jpg|jpeg|gif|ico|svg|woff2?)$" || req.url ~ "^/api/") { unset req.http.cookie; set req.http.X-Ignore-Cookie = "true"; } if (req.http.X-Ignore-Cookie == "true") { unset req.http.cookie; }}

注意:unset req.http.cookie 必须在 return (hash) 前执行;否则 Varnish 仍按带 Cookie 的逻辑区分缓存键。

调试缓存是否真正生效的三步验证法

别只看浏览器响应头——那可能是 Nginx 回的。要确认真实路径:

用 curl -I http://your-domain.com/test.html,检查响应头中是否有 X-Varnish: 和 X-Cache: HIT(不是 X-Cache: HIT from nginx)登录 Varnish 服务器,运行 varnishadm backend.list 确认后端健康;再执行 varnishadm ban.list 看是否有误清除规则残留临时在 Nginx 的 location / 块里加 add_header X-Proxy-By "nginx->varnish";,再 curl 验证该 header 是否出现——若没出现,说明请求根本没走这个 location

最易被忽略的一点:Varnish 的缓存键(hash_data)默认包含 req.http.host 和 req.url,但如果你在 Nginx 层做了 rewrite 或 proxy_redirect,而没同步更新 Varnish 的 vcl_hash,会导致相同内容被存多份、命中率骤降。此时必须自定义 vcl_hash 并显式 hash_data(req.url)。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。