一次小功能上线后,商品页 TTFB 从 150ms 涨到 1.8s。Varnish 没报错,缓存刷新也正常,但每次请求都回源。最后只是一段 layout XML 给自定义 block 加了 cacheable="false"。

Magento 的规则很直接:可缓存页面中只要有一个 block 不可缓存,整页就不能进入 Full Page Cache。它不是“只有这个小块不缓存”。所以把会员名字、购物车数量或实时库存直接做成不可缓存 block,代价可能是所有商品页都动态渲染。

先证明页面确实没有进入 FPC

curl -sS -D - -o /dev/null https://shop.example.com/product.html
curl -sS -D - -o /dev/null https://shop.example.com/product.html

比较两次请求的 Age、X-Magento-Cache-Debug 或 Varnish 命中标记。确认不是 Cookie、Authorization、查询参数或 CDN 规则主动 bypass 后,再查 layout。

不要只搜索自己模块

最终 layout 来自主题、核心模块和所有扩展合并。搜索所有 cacheable="false",再按当前 full action name 确认它是否真的落在商品页。某个 default.xml 的设置影响范围可能比开发者想象大。

grep -R 'cacheable="false"' app/code app/design vendor/*/*/view/frontend/layout -n

临时禁用可疑模块或 layout handle 做对照,避免仅凭文件名下结论。开发者工具中的 profiler 和响应头可以帮助确认页面恢复缓存后的变化。

个性化内容应该怎么放

购物车数量、欢迎语、客户专属提示适合 customer-data/private content,由浏览器在公共页面加载后补齐。真正必须实时请求的数据,可以做小型 AJAX/GraphQL 接口,并设置清楚的超时与失败降级。不要为了一个十几字的客户名字牺牲整个 FPC。

如果 block 内容其实对所有用户相同,只是更新频率较高,可以使用正确 cache key、cache lifetime 和 identity tag,而不是直接关闭缓存。实体保存时精准失效,比把页面永久设成 MISS 更可控。

修复后不能只看首页变快

我会连续请求商品页、分类页和 CMS 页,确认第二次命中;再测试登录用户的私有内容没有串号,购物车数量能更新,退出登录后数据被清理。最后比较 PHP-FPM 请求数和 Varnish hit rate。性能恢复与个性化正确必须同时成立。