Varnish必须监听80端口才适合生产环境,修改方法为:Ubuntu/Debian编辑/etc/default/varnish,CentOS/RHEL编辑/etc/sysconfig/varnish,将监听端口从6081改为80,并重启服务;若端口被占用需先停用nginx或httpd。

直接上结论:Varnish 不适合装在默认端口 6081 上跑生产网站,必须改监听端口为 80,否则浏览器访问时得手动加 :6081 —— 这不是缓存加速,是自找麻烦。
怎么让 Varnish 监听 80 端口而不是 6081
Varnish 默认只监听 :6081,这是开发调试用的,不能直接对外服务。改端口不是改 default.vcl,而是改系统级服务配置文件:
- Ubuntu/Debian:编辑
/etc/default/varnish,找到DAEMON_OPTS行,把-a :6081改成-a :80 - CentOS/RHEL/Rocky:编辑
/etc/sysconfig/varnish,修改VARNISH_LISTEN_PORT=80 - 改完必须重启服务:
sudo systemctl restart varnish - 如果提示
Address already in use,说明nginx或httpd正占着 80 端口 —— 它们得关掉或改到其他端口(比如8080),Varnish 才能接流量
后端地址写错会导致 503 Service Unavailable
default.vcl 里 backend 块配错,Varnish 就连不上真实 Web 服务器,所有请求都返回 503。常见错误有:
- IP 写成
127.0.0.1,但后端实际在另一台机器上(比如192.168.10.20) -
.port写成"80",但后端服务实际监听的是8080或3000 - 用了域名但没配 DNS 或
/etc/hosts,Varnish 解析失败(建议初期全用 IP) - 后端开了防火墙,没放行 Varnish 所在机器的 IP(CentOS 的
firewalld默认拦所有入向连接)
验证方法:在 Varnish 服务器上执行 curl -v http://192.168.10.20:8080,能通才说明网络和端口没问题。
缓存不生效?检查 vcl_recv 里是否误加了 return(pass)
很多用户照抄示例,在 vcl_recv 里写了类似下面这种“防爬虫”逻辑:
if (req.url ~ "^/admin" || req.http.User-Agent ~ "Baiduspider") {
return (pass);
}
问题在于:一旦命中 return(pass),Varnish 就绕过缓存直连后端,所有请求都是 MISS。真实场景中,要谨慎判断哪些路径真不该缓存:
- 登录页、支付回调、API 接口通常该
pass - 静态资源(
.js、.css、.png)默认就该缓存,别一并pass - 没加
return(hash)或漏掉return(lookup)(Varnish 6+ 已弃用,新版用return(hit_for_pass)或return(miss))也会导致行为异常
最简验证方式:临时清空 vcl_recv,只留 return (hash);,再测缓存头 X-Cache 是否出现 HIT。
缓存清除命令 varnishadm ban 失效的三个原因
varnishadm ban.url /path 清不掉缓存,大概率不是命令写错,而是:
- Varnish 没启用
ban功能:确认/etc/varnish/default.vcl里有没有sub vcl_hit或sub vcl_miss中调用ban()的逻辑(新版 Varnish 7 默认支持,老版本需显式启用) - ban 规则没匹配上:URL 是大小写敏感的,
ban.url /index.html清不掉/INDEX.HTML;带查询参数的 URL 要写全,比如ban.url ^/article?id=123$ - 执行命令的用户权限不够:
varnishadm默认只允许varnish用户或 root 执行,普通用户会报Connection refused
真正稳妥的清除方式是先查命中情况:varnishlog -g request -q "ReqUrl ~ '^/test'",再针对性 ban,别盲目 ban.url .*$ —— 那会清空全部缓存,后端瞬间承压。
最常被忽略的一点:Varnish 的缓存对象生命周期由 beresp.ttl 和后端响应头中的 Cache-Control 共同决定,如果你的后端没设 Cache-Control: public, max-age=3600,Varnish 默认只缓存 120 秒(VARNISH_TTL 值),而且这个值在 vcl_backend_response 里才能真正覆盖。


















