笔记

API 更新了,博客页面为什么还是旧的?

一次发布 11 篇文章后,内容 API 已经能查到新文章,博客列表却没有更新。给列表 URL 加一个新的查询参数,同一个页面又能显示全部内容。

这个站点从内容 API 读取 Markdown 索引,再由 Nuxt 在服务端生成页面。API 与页面不是同一个缓存对象,检查到前者更新,并不能说明后者已经更新。

加参数就正常,能说明什么?

普通 /posts 的 HTML 缺少新文章,响应头仍带着旧缓存信息:

snippet
http
Cache-Control: s-maxage=3600, stale-while-revalidate
X-Cache: HIT
Last-Modified: <旧时间>

新参数地址返回 MISS,HTML 中有全部新文章。两份响应的差异说明:应用有能力生成新页面,但普通地址仍在命中某份旧对象。

还不能仅凭 X-Cache 就确定是哪一层。应用数据缓存、整页缓存、反向代理和浏览器,都可能参与请求,需要把返回的正文与各层配置对起来。

这种更新问题,通常有哪些处理方式?

可以等待缓存过期、让发布流程主动失效相关对象,或者关闭不适合当前更新频率的缓存。选择取决于允许读者看到多旧的数据,以及愿意承担多少重新渲染开销。

排查时先把链路列出来更有用:内容文件变成 API 索引与详情,页面再取数据生成 HTML,HTML 可能被上游代理保存,最后才到浏览器。最外层直接回旧 HTML 时,请求根本不会到达内容 API,重启 API 自然影响不到它。

这次先调整应用层,再继续对照部署后的普通地址,没有把新参数能看到内容当作排查结束。

应用改成 no-store,为什么还没好?

站点先取消列表、标签和详情路由的整页 SWR,响应改成 Cache-Control: no-store。数据读取缓存仍保留:索引 60 秒,详情 10 分钟。这样页面重新进行服务端渲染,但底层数据还能短暂复用。

代价是服务端渲染次数增加,详情仍可能读到十分钟前的数据,已打开页面也不会自动刷新。这是当时接受的更新与开销取舍。

本地生产构建连接真实内容 API 时,新文章和新响应头都正常。部署后,新参数地址能拿到 no-store,普通 /posts 却仍是 HIT 和旧正文。新的响应头没有清掉上游已经保存的旧对象,请求在到达新应用前就返回了。

最后怎样确认是代理缓存?

检查目标站点代理时,面板缓存开关虽然关闭,配置中却没有显式禁用对应位置的缓存。补上下面这一行后,再访问普通地址:

snippet
nginx
proxy_cache off;

旧 HIT 消失,HTML 中缺少的新文章数量从 11 变成 0。这次关闭的是目标位置对缓存的使用,没有物理删除服务器缓存目录,也没有继续追完所有配置继承来源。

收尾仍检查读者平时访问的 /posts、/tags 和文章详情,对照状态码、缓存头及正文。带参数地址只用于比较,不能替代原 URL 的验收。本篇记录的是当时的处理过程,本次整理没有重新核查线上配置。

返回上一页