事情本身不复杂,线索都在日志里。Varnish 6 开了 grace 模式,后端一慢就返回过期对象。蜘蛛上午抓到的首页还是两小时前的版本,新文章一直不进索引,用户也要刷新几次才看到。

第一反应是「缓存键没带版本号,发布后旧对象仍然命中」,验证下来不成立。

原因不止一个,得分开看。beresp.grace 设成两小时,过期对象被继续返回。另一种情况是后端 5xx 时 req.grace 生效,错误期被拉长。

不容易想到的是,没有给新文章路径单独设短 TTL。

动手时先看响应头里的 Age

curl -sI https://www.example.com/ | grep -i age

接着把 grace 收到 30 秒

sub vcl_backend_response { set beresp.grace = 30s; }

首页与列表页跳过缓存

if (req.url ~ "^/(|category/)") { return (pass); }

发布后按标签清理

varnishadm ban 'req.http.host == "www.example.com" && req.url ~ "^/"'

同样的操作我在测试机上先走了一遍,线上只做验证过的部分。

恢复的判定其实很直接。响应头 Age 不再超过 60 秒,蜘蛛抓到的是新版本,新文章当天进索引。

grace 是给用户兜底的,不是给爬虫看旧内容的理由,首页和列表页最好单独缩短窗口。报错文案容易误导,真正的原因往往在相邻那一层的日志里。

作者 9823189