写下“访问链路”这个词的时候,我知道大部分读者脑中没有画面。DNS、TLS、CDN、TTFB 这些词单独看都懂,连起来却很难想象一次请求到底经过了什么。

于是我想做一个可视化:把一次真实访问拆成几个节点,标上耗时,让读者一眼看到时间花在哪里。

素材来自一次真实请求

我没有编造数据,而是抓了一次自己的访问:

1
2
3
curl -o /dev/null -s -w \
'dns=%{time_namelookup} connect=%{time_connect} tls=%{time_appconnect} ttfb=%{time_starttransfer} total=%{time_total}\n' \
https://example.com/

得到一组数字之后,我又从浏览器性能面板里取了资源加载和渲染的时间。两组数据拼起来,才是一条完整的链路:

1
DNS → TCP → TLS → 等待响应 → 下载 HTML → 加载资源 → 渲染

第一版:动态图,失败

第一版我用 D3 做了一个动态图:节点会依次亮起,连线有流动效果,鼠标悬停显示耗时。

做出来很酷,但很快发现三个问题:

  • 读者要等动画播完才能看全,反而更慢;
  • 动态效果吸引了注意力,但没帮助理解;
  • 多了一个前端依赖,页面变重,和文章主题自相矛盾。

这一版被我删掉了。它更像一个演示,而不是一个解释工具。

第二版:手绘 SVG,信息过载

第二版我改用静态 SVG,手写坐标。为了“信息完整”,我把每个节点的耗时、协议、状态码、缓存命中情况都标了上去。

结果是图很满,读者不知道先看哪里。我在图下面写了三段说明,仍然有人问“这条线是什么意思”。

问题不在于画得不好,而在于我想在一张图里塞下太多信息。可视化不是把数据全部摊开,而是帮读者建立一个主要印象。

第三版:只保留六个节点

最后一版只保留六件事:

  1. 输入域名;
  2. DNS 解析;
  3. 建立连接与 TLS;
  4. CDN 或源站响应;
  5. 下载关键资源;
  6. 首屏渲染。

每个节点只标一个耗时,用横条长度表示占比。颜色只用两种:常规耗时和明显偏慢的节点。图下面配一句话结论:“这次访问里,大部分时间花在图片下载上。”

为了让图不依赖 JavaScript,我用 SVG 直接画,宽高固定,移动端等比缩放。数据来自一次真实请求,图注里写明了采样时间和网络条件。

反馈

我把图发给几个不写代码的朋友看,问他们“这张图在说什么”。大部分人的回答是“页面加载慢在图片”,这正是我想传达的。

也有读者问:“为什么 DNS 这么快?”这让我意识到,图能引出问题,本身就是好事。我在图下面补了一小段解释,说明 DNS 命中缓存时会很快,冷启动时可能慢得多。

学到的事

这次实验让我对“可视化”有了更实际的理解:

  • 先确定一句话结论,再决定画什么;不是先画图再找结论;
  • 减少维度,一张图只讲一件事;
  • 标注数据来源和条件,否则图会变成误导;
  • 静态图往往足够,交互和动画只在确实需要探索时才有价值;
  • 考虑页面重量,解释链路的图自己不应该成为链路的负担。

最后

这张图现在放在一篇讲访问链路的文章里,不大,也不炫。它没有让我拿到什么奖项,但有读者说“终于知道慢在哪了”。

对个人站点来说,这大概就是可视化最实际的价值:不是展示技术,而是把一件复杂的事,讲到别人能复述出来。