TTFB 完全拆解:从浏览器到首字节的 6 个阶段,哪一段慢了你都得知道

分类:测速指南 发布时间:2026-05-24

"我的网站打开 3 秒,TTFB 就占了 1.8 秒。"——这是站长群里几乎每天都有人在问的问题。TTFB(Time To First Byte,首字节时间)是衡量网站响应速度的核心指标,但它不是一个原子操作,而是由 6 个独立阶段串联而成。任何一段出问题都会让 TTFB 数字飙升,而排查方向截然不同。

这篇文章会把 TTFB 这一个数字拆成 6 段,每段给出健康/警戒/病态的数值基准,并告诉你每一段如果慢了应该用什么工具定位、怎么优化。读完之后再看到"TTFB 1.8 秒",你就知道该从哪一步开始查。

一、TTFB 是什么,包含哪 6 个阶段

TTFB 严格定义是:浏览器发起请求开始,到收到响应的第一个字节为止所经历的时间。看似只有"发请求—收响应"两步,实际上中间藏了 6 个子阶段:

  1. DNS 解析:把域名翻译成 IP 地址
  2. TCP 连接:浏览器和服务器握手建立 TCP 通道
  3. TLS 握手:HTTPS 站点协商加密通道(HTTP 站点跳过此步)
  4. HTTP 请求发送:把请求报文发到服务器
  5. 服务器处理:服务器跑业务逻辑、查数据库、渲染响应
  6. 首字节响应:服务器把响应第一个字节通过网络回传给浏览器

用一张表把这 6 段在浏览器开发者工具(Chrome DevTools Network 面板)里的对应字段列出来:

阶段DevTools 字段健康值警戒值病态值
DNS 解析DNS Lookup< 30ms30-100ms> 100ms
TCP 连接Initial connection< 50ms50-150ms> 150ms
TLS 握手SSL< 100ms100-300ms> 300ms
请求发送Request sent< 5ms5-50ms> 50ms
服务器处理Waiting (TTFB)< 200ms200-600ms> 600ms
首字节传输< 50ms50-200ms> 200ms

注意一个常见混淆:Chrome 把 "Waiting" 字段也叫做 TTFB,但这只是"服务器处理时间",跟整体 TTFB(从发起请求到收第一字节)不是一回事。本文统一用"整体 TTFB"指完整的 6 段总和,用"服务器处理"指 Chrome 的 Waiting 字段。

二、阶段 1:DNS 解析慢——80% 的人没意识到的隐形成本

DNS 解析是请求生命周期的第一步,但很多人完全忽略它的性能影响。一个未优化的 DNS 解析在国内可能要 200-500ms,这一段比"服务器慢"还要难发现,因为它不在你的服务器日志里。

怎么判断 DNS 是不是慢

用 dig 命令直接测:

dig www.example.com @114.114.114.114
# 看输出的 Query time

dig www.example.com @8.8.8.8
# 对比不同公共 DNS

或者用本站的 DNS 查询工具,从全国多节点测试解析速度。如果不同地区差异巨大(北京 30ms、广州 280ms),说明你的权威 DNS 服务器节点不够分散。

DNS 慢的常见原因

  • 使用了境外权威 DNS:很多人把域名 DNS 托管在 Cloudflare/Namecheap 等境外服务,国内解析要绕到香港/日本
  • NS 记录只有一台:单点故障 + 缓存击穿时解析雪崩
  • TTL 设置过短:DNS 缓存频繁失效,每次都要回源
  • 权威服务器地理分布差:所有 NS 都在同一个机房

优化建议

把权威 DNS 换成国内有 BGP 节点的厂商(DNSPod、阿里云 DNS、华为云 DNS),TTL 设置 600-3600 秒(不要短于 300,太短会被频繁回源)。对核心域名可以同时配置 2-3 家 DNS 服务商做冗余。

三、阶段 2:TCP 连接慢——大多数情况只看一个数字

TCP 三次握手的时间,几乎完全等于用户到服务器的物理网络 RTT。这是 6 个阶段里最难"优化"的——光速就那么快,北京到洛杉矶单程 150ms 是物理极限。

TCP 阶段在测什么

三次握手包含 SYN → SYN-ACK → ACK。前两步耗时基本等于一个 RTT。Chrome 显示的 "Initial connection" 时间,约等于客户端到服务器的一个 RTT 加上 TCP 协议栈处理开销

怎么判断 TCP 是不是慢

用本站的 TCPing 工具,直接对你网站的 443 端口或 80 端口测试。把测得的延迟和该地区到该机房的"基线延迟"对比:

路线典型 RTT
国内同省同运营商5-20ms
国内跨省跨运营商20-60ms
大陆 → 香港30-80ms
大陆 → 日本50-120ms
大陆 → 美国西海岸140-200ms
大陆 → 美国东海岸180-280ms
大陆 → 欧洲200-300ms

如果实测明显高于基线,问题不在"距离"而在"绕路"。这时要用 路由追踪 / MTR 工具 看 IP 包是从哪里开始绕的。常见的"绕路"包括:电信走美国回亚洲、联通走欧洲到日本等运营商出口问题。

优化建议

  • 用 CDN 把用户和"边缘节点"的距离拉近,让 TCP 握手只在用户和最近边缘之间发生
  • 启用 TCP Fast Open(TFO):让握手和首个请求合并,但需要客户端和服务端都支持
  • 升级到 HTTP/3(QUIC):QUIC 基于 UDP,0-RTT 握手在重连场景下能省掉一整个 RTT

四、阶段 3:TLS 握手慢——HTTPS 的"双倍开销"

HTTPS 站点比 HTTP 站点 TTFB 高的根源就在这里。完整的 TLS 1.2 握手需要额外 2 个 RTT,TLS 1.3 优化到 1 个 RTT,会话复用可以做到 0-RTT。

TLS 握手开销分布

TLS 版本新连接会话复用
TLS 1.22 RTT1 RTT
TLS 1.31 RTT0 RTT

所以一个用户的"首次访问"和"二次访问"TTFB 差异巨大——首次要完整握手,再访问可以走会话复用。如果你的 TLS 握手时间稳定在 300ms+ 不下来,最可能的原因不是延迟,而是握手过程中证书链验证太慢

怎么判断 TLS 是不是慢

用 openssl 命令直接量化:

openssl s_client -connect www.example.com:443 -servername www.example.com < /dev/null

# 看输出里 "SSL handshake has read X bytes and written Y bytes" 之前的耗时

或者用本站的 HTTP 测试工具,它会单独显示 TLS 握手耗时。

TLS 慢的常见原因和优化

  • 证书链太长:每多一级中间证书,浏览器要多验证一次。优化方案是让 Nginx 配置时把完整证书链(fullchain)拼起来,而不是只发服务器证书让浏览器自己去补
  • OCSP 检查阻塞:浏览器要在线检查证书是否被吊销。优化方案是 Nginx 开启 ssl_stapling on
  • 用了较老的密钥交换算法:比如 RSA-2048。改成 ECDHE + ECDSA 可以让握手快 30-50%
  • 没启用 Session Resumption:Nginx 配置 ssl_session_cache shared:SSL:10m;ssl_session_timeout 1h;
  • 升级到 TLS 1.3:协议层面减少一个 RTT

五、阶段 4:请求发送——基本不会成为瓶颈

"Request sent" 是把 HTTP 报文从浏览器写到 TCP 套接字的时间,绝大多数情况下这一步在 1-5ms 之间,是 6 段里最不需要担心的。

如果这一段超过 50ms,通常是请求体异常大(比如带了几 MB 的 cookie,或者 POST 上传大文件)。检查浏览器开发者工具的 Request Headers 总大小,如果超过 16KB 要考虑减小 cookie。

六、阶段 5:服务器处理——TTFB 的"主战场"

这是 Chrome 显示的 "Waiting (TTFB)",也是大多数 TTFB 优化文章实际在讲的部分。服务器收到完整请求后到产出第一个字节的全部内部处理时间。

这一段可能慢的原因

按出现频率从高到低:

  1. 数据库慢查询:单个 SQL 100ms+,或者一个页面查 30 次数据库
  2. 缺少缓存:每次请求都从源头计算/查询
  3. 外部 API 阻塞调用:等支付接口、推送接口等同步返回
  4. PHP/Python 应用启动开销:FPM 进程不够导致排队,或 Python 应用没用 WSGI 复用
  5. 磁盘 IO 瓶颈:日志写入慢、模板文件多次读取
  6. CPU 跑满:服务器流量太大或代码效率差

怎么定位是哪个子原因

不能只看"服务器慢"四个字。在服务器端开启慢日志

  • Nginx 慢日志:access_log$request_time 字段
  • PHP-FPM 慢日志:slowlog + request_slowlog_timeout 1s
  • MySQL 慢查询:slow_query_log = ON + long_query_time = 0.5
  • 应用层 APM:阿里云 ARMS、腾讯 APM、Sentry Performance 等

常用优化手段

问题优化方案预期收益
数据库慢查询加索引、慢查询日志逐个查50-90%
无缓存Redis/Memcached 缓存热数据80-99%
页面渲染慢Nginx 缓存整页(fastcgi_cache)90-99%
外部 API 阻塞异步队列 + 占位响应因场景
PHP-FPM 进程不够调大 pm.max_children看负载
静态资源混在动态请求里分离到独立 location30-50%

七、阶段 6:首字节传输——和距离相关,和带宽无关

服务器产出第一个字节后通过网络传回客户端的时间。这一段又是一个 RTT 的一半(单程),所以基本无法在应用层优化。

这一段慢通常只有一种情况:服务器到用户之间的网络抖动。一般 TCP 阶段就能看出来,但偶尔会出现 TCP 握手时网络好、传输首字节时刚好赶上抖动。

排查方法是用 路由追踪工具 在用户出问题的时段抓一遍 MTR,看是不是某一跳出现 10%+ 丢包。

八、一个真实排查案例

用一个我们见过的真实案例串起来。某电商站点反馈"首页打开 3 秒",用户在广东电信。

用浏览器开发者工具看 Network 瀑布图:

阶段实测耗时评估
DNS Lookup320ms病态
Initial connection180ms警戒
SSL410ms病态
Request sent2ms正常
Waiting (TTFB)1850ms病态
Content Download240ms正常

3 个红灯,分别对应 3 个不同的问题。把这种"宏观慢"拆成"3 个具体问题",才能各个击破

  1. DNS 320ms:查权威 DNS,发现用了某境外厂商,国内解析绕香港。换成 DNSPod 后降到 25ms
  2. SSL 410ms:Nginx 没配 OCSP Stapling 也没配 Session Cache,TLS 协议还是 1.2。开启 stapling、加 session cache、升级 OpenSSL 后降到 110ms
  3. Waiting 1850ms:开 PHP-FPM 慢日志,发现首页一个查询商品分类的 SQL 跑了 1.6 秒(没加索引)。加索引后降到 80ms

三处优化合计降低 TTFB 约 2500ms,整体页面首屏从 3 秒优化到 600ms。关键是先拆解再分析,不要看到"慢"就只盯着服务器

九、TTFB 自检清单

下次再遇到 TTFB 高,按这个清单走一遍:

  1. 打开 Chrome 开发者工具 Network 面板,刷新页面,点击主请求看 Timing 标签
  2. 记下 6 个阶段的耗时,对照本文表 1 的健康/警戒/病态阈值
  3. 找出第一个超过警戒值的阶段,先处理它
  4. 处理完一个阶段,再次实测,验证下降到健康区间再继续下一个
  5. 不要同时改多个变量,否则不知道哪个优化生效了

需要多节点验证 TTFB 的话,可以用本站的 HTTP 测试工具,从全国多地实测你网站的完整 6 段耗时,定位是某地区独有问题还是全国性问题。

"TTFB"从来不是一个数字,而是 6 个数字的总和。把它拆开看,优化才会有方向。

← 返回测速指南列表 返回首页