跳到主要内容

我在自己的网站,查出了别人的问题

摸鱼办主任
摸鱼办主任

· 阅读约 4 分钟

一个 2,068 毫秒的时间段,正好占一次页面加载的 49%。

这 2 秒里浏览器在干什么?在等。不是加载脚本,不是解析 HTML,是连第一个字节都没收到——服务器那头一直没动静。Anna Villarreal 把这个数字截图放出来的时候,我甚至能想到她盯着 Sentry 面板时的那种表情:先皱眉,再翻源码,怀疑人生十分钟,最后意识到问题根本不在她自己的代码里。

这个惨案全貌是这样的:她给个人网站接上 Sentry 看流量,结果 trace 里明晃晃写着,页面要 4.2 秒才能加载完。拆开细看,TTFB 占了一半。对,就是那个前端工具几乎从来不给你显示的数字。

我自己的网站也慢,但我的排障顺序永远是:先骂自己写的烂代码,再怀疑服务器配置,最后才想起来看一眼是不是哪个第三方接口在拖后腿。而 TTFB 这个东西最坑的地方在于它的发生时机很早——早到你的 JS 还没开始跑,早到你所有熟悉的性能面板都还来不及记录。它就像一个站在后台偷偷抽烟的厨师,你看着一桌菜干着急,压根不知道烟是后厨抽的。

然后她用了 Sentry 的 Seer 去定位。这步挺神的——一个 AI 把范围缩到一个具体的接口上:本站拉取 dev.to 文章列表的那个请求,平均 361 毫秒,p95 冲到 1.37 秒。你说这算慢吗?单看还好,但套在一个本来就要 4 秒的页面上,这就是压垮骆驼的最后一根稻草。更关键的是,那个接口是 dev.to 的,不是她写的,不归她控制。她在自己的一亩三分地上,查出了一个别人家服务的慢性病。

然后她的操作就很经典了:不优化代码了,直接骗过去。nginx 开 proxy_cache_background_updateproxy_cache_use_stale,设个 15 分钟 TTL——意思就是:用户来拿文章列表,先赏一份可能过期的旧数据垫垫肚子,nginx 自己再偷偷去后台刷新缓存。从用户视角,页面快得像家门口的小卖部;从 dev.to API 视角,请求都被后端兜住了,真正的调用次数直接腰斩再腰斩。p50 从 3.3 秒降到 1.3 秒,前后不到一天。

这个操作让我笑了很久。它本质上是我们这行的通用解法:遇到一个你改不了的慢系统,就别硬碰,在自家门口绕条路。效果立竿见影,代价是页面可能偶尔显示旧数据——但对一个文章列表来说,旧个十五分钟谁在乎?有意思的是那个对比数字:优化后 GET 接口走缓存 90 毫秒搞定,直连 dev.to 的裸请求在 74 到 832 毫秒之间蹦。看这个区间你就知道对方服务器的心情有多不稳定。

评论区有个叫 Ofri Peretz 的伙计说了句很到位的话:这个 2068 毫秒的 TTFB,绝大多数前端工具对它是瞎的。你在 Chrome DevTools 里能看到资源瀑布图,能看到 JS 执行时间,但"浏览器等服务器开口说话"这个时间段是透明的。另一个哥们儿更实诚,说他平时把 Sentry 当纯错误通知用,压根没想到 trace 还能干这活。Anna 回他说 trace 能把延迟分配到具体责任人——这话翻译成人话就是:以后再有人怪你网站慢,你可以甩一张截图说,看,锅在那边,不在我们家。

这个案例最让我有共鸣的地方在于它的荒谬感。她装 Sentry 的原始动机是"分析流量和性能",听起来像要做正经前端优化,但最后真正的问题是第三方 API 的延迟。等于你请了个体检医生,结果查出来你邻居得了流感。

不过要说这故事教会了我什么实质的东西,大概就一句话:下次你网站慢,先看一眼 TTFB 那个没人看的数字,再决定要不要骂自己写的代码。

(友情提示:Anna 那篇文发在 DEV 的 Summer Bug Smash 活动里,你要是搜不到也别急,你大概率没有把 49% 的时间浪费在这些细枝末节上。)