返回博客列表

TTFB高是什么原因?CDN和源站应该先查谁

CdnChart 技术团队发布于 2026-09-2214 分钟阅读
TTFB高是什么原因?CDN和源站应该先查谁

网站打开慢,测速结果里TTFB又特别高,接下来经常出现一场熟悉的争论。

CDN厂商说:“边缘节点没有问题,慢的是源站。”

服务器运维说:“源站在机房里响应很快,肯定是CDN线路不行。”

双方都能拿出一张看起来有道理的截图,但用户那边仍然要等两三秒才能看到页面。

TTFB高时,CDN和源站到底应该先查谁?答案不是固定的。先看测试口径,再看缓存状态,最后用同一个URL做对照。

如果缓存HIT的静态资源TTFB依然很高,优先检查用户到CDN节点的连接、节点调度和边缘处理;如果HIT很快、MISS或动态请求很慢,排查重点就应该转向回源链路、源站程序和数据库。

不要一上来就站队。先把慢的那一段找出来,责任通常会自己浮出来。

TTFB到底是什么?它不只是“服务器处理时间”

TTFB是Time to First Byte的缩写,表示从开始请求到响应的第一个字节到达所经历的时间。

问题在于,不同工具对“开始”的定义和阶段展示方式可能不完全相同。

浏览器导航层面的TTFB,可能包含:

  • 页面重定向;

  • Service Worker启动;

  • DNS解析;

  • TCP或QUIC连接;

  • TLS协商;

  • 请求发送和网络往返;

  • CDN边缘节点处理;

  • 缓存未命中后的回源;

  • 源站程序准备响应。

web.dev将导航请求的TTFB描述为从开始导航到响应首字节到达,并明确列出了重定向、Service Worker、DNS、连接、TLS和请求等待等阶段。

这意味着浏览器里看到TTFB高,并不能直接等同于“后端代码执行时间高”。详见web.dev的TTFB说明

Chrome开发者工具在单个请求的Timing面板里,会进一步把排队、DNS、连接、TLS、请求发送、等待TTFB和内容下载拆开。

此处的“Waiting for server response”更接近请求发出后等待首字节的阶段,但仍包含网络往返和服务器准备响应所需时间。可参考Chrome DevTools Network文档。

所以,在比较两张TTFB截图之前,先确认它们来自什么工具、测试哪个URL、是否发生重定向、连接是否复用,以及测量的是完整导航还是单个HTTP请求。

TTFB多少算正常?0.8秒只能作为参考线

web.dev给出的粗略建议是,大多数网站可以争取让75%用户的TTFB保持在0.8秒以内;超过1.8秒通常属于较差范围。

同时它也强调,TTFB不是Core Web Vitals指标,这些阈值需要结合网站交付方式理解。

这组数字适合做网页体验参考,但不应该变成所有业务、地区和资源的统一SLA。

例如:

  • 同城缓存HIT的小型静态文件,通常应该比跨洲动态接口更快;

  • 登录后的个性化页面,无法简单套用公共静态资源标准;

  • 首次HTTPS连接与连接复用后的请求,耗时不同;

  • 用户在中国大陆访问海外源站,与当地用户访问同一源站,基线不同;

  • 单次测试达到0.7秒,不代表晚高峰的P95同样正常。

比“有没有低于0.8秒”更有价值的,是建立自己的基线:同一个URL、同一地区、同一运营商、相同缓存状态下,P50和P95分别是多少,最近是否出现持续变化。

先看缓存状态,它是判断CDN还是源站的第一条分界线

CDN已经缓存的资源和需要回源的资源,走过的路径不同。

缓存HIT时

请求通常在边缘节点直接得到响应,不需要等待源站完整处理。

此时TTFB仍然高,优先检查:

  • 用户是否被调度到了较远节点;

  • 节点与当前运营商的线路是否绕路或拥塞;

  • DNS、TCP或TLS阶段是否过长;

  • 边缘节点是否负载较高;

  • WAF、Bot、鉴权或边缘函数是否增加处理时间;

  • 请求是否发生重定向;

  • 测速工具是否把连接阶段计入TTFB;

  • 所谓HIT是否来自浏览器本地缓存,而不是CDN边缘缓存。

缓存MISS、BYPASS或动态请求时

CDN节点需要连接源站并等待响应。

除了用户到CDN这一段,还多出了CDN回源连接、源站TLS、程序处理和数据返回等过程。

这时应该检查:

  • CDN节点到源站的网络路径;

  • 源站所在地区是否离边缘节点过远;

  • 回源连接能否复用;

  • 源站防火墙或WAF是否延迟请求;

  • 源站CPU、内存、磁盘、连接数是否饱和;

  • 应用工作进程和连接池是否排队;

  • 数据库查询、锁和缓存是否异常;

  • 外部API是否拖慢整个响应;

  • 缓存规则是否导致本可缓存的内容频繁回源。

不同CDN对缓存状态使用的响应头并不统一。常见值包括HITMISSBYPASSDYNAMICEXPIREDREVALIDATED,但具体含义应以当前服务商文档为准。

以Cloudflare为例,其官方文档使用CF-Cache-Status描述缓存结果,并分别解释HIT、MISS、BYPASS、DYNAMIC、EXPIRED等状态。

这可以作为理解缓存状态的一个实例,但不能把同一套响应头名称照搬到所有CDN。详见Cloudflare缓存响应说明

缓存头的详细判断方法,可以继续参考《CDN缓存命中怎么看?HIT、MISS和Age怎么理解》

用四组对照测试,判断慢在哪一段

单独测一次首页,很难分清CDN和源站。更实用的办法是准备几类可控的测试对象。

测试对象

用来观察什么

需要控制的条件

CDN缓存HIT的固定静态文件

用户到边缘节点及边缘处理

URL、文件、节点、协议保持一致

CDN缓存MISS的测试文件

CDN回源路径和首次响应

使用专门测试对象,不污染生产缓存

经CDN访问的动态接口

完整动态回源表现

接口只读、无敏感参数、返回稳定

授权环境中的源站对照

源站自身响应能力

保持Host、TLS、路径和请求头一致

结果可以这样理解:

对照结果

更值得优先排查的方向

HIT高,MISS也高

用户到边缘节点、DNS/TLS、节点负载或边缘规则

HIT低,MISS高

CDN回源链路、源站或缓存规则

CDN MISS高,授权源站对照也高

源站程序、数据库、外部依赖或服务器资源

CDN MISS高,源站对照低

CDN到源站的网络、回源TLS、连接复用或源站对CDN请求的处理差异

本地都低,某些地区高

CDN调度、区域节点或运营商线路

单次低、P95高

高峰拥塞、资源排队或偶发依赖超时

静态文件低、首页HTML高

动态页面、重定向、应用程序或数据库

这张表用于确定排查顺序,不是直接判定责任方。

比如“源站对照低、CDN MISS高”,也可能是源站只对本地测试IP响应快,对CDN回源IP触发了防火墙检查或限速。

第一步:确认你测的是同一个请求

很多CDN与源站争论,最后发现双方测的根本不是同一件东西。

正式比较前,先统一以下条件:

  • 完整URL相同,包括路径和查询参数;

  • HTTP方法相同;

  • Host、User-Agent、Cookie和必要请求头相同;

  • 最终状态码和响应内容相同;

  • 是否跟随301、302重定向的规则相同;

  • IPv4或IPv6保持一致;

  • 缓存HIT、MISS和动态请求分开;

  • 测试地区、运营商和时间接近;

  • 文件大小及压缩方式相同;

  • 每个测试单元具有足够且相近的样本量。

特别要检查最终返回的内容。HTTP 200不一定代表拿到了正确页面,WAF验证页、默认站点和软错误页面也可能返回200。

第二步:用curl记录连接和首字节时间

下面的命令会输出响应头、最终状态码、解析IP、重定向次数及各阶段累计时间:

curl -L -sS -o /dev/null -D - \
  -w '\nstatus=%{http_code}\nurl=%{url_effective}\nremote_ip=%{remote_ip}\nredirects=%{num_redirects}\ndns=%{time_namelookup}\nconnect=%{time_connect}\ntls=%{time_appconnect}\nredirect_time=%{time_redirect}\nttfb=%{time_starttransfer}\ntotal=%{time_total}\n' \
  https://www.example.com/test.html

curl官方手册对这些字段的定义包括:

  • time_namelookup:从开始到域名解析完成;

  • time_connect:从开始到TCP连接完成;

  • time_appconnect:从开始到TLS等连接完成;

  • time_starttransfer:从开始到收到第一个字节;

  • time_total:整个操作完成;

  • time_redirect:进入最终请求前,前面所有重定向消耗的累计时间。

可查看curl官方手册核对字段含义。

这些时间多数是从请求开始累计计算,不能直接相加。例如time_starttransfer已经包含前面的解析、连接及等待过程。

同一个URL建议连续测试多次,并覆盖不同时间段。第一次与后续结果差距较大时,要继续检查连接复用、DNS缓存和CDN缓存状态。

第三步:在浏览器里拆开等待TTFB之前的时间

Chrome开发者工具可以帮助回答一个关键问题:高的是DNS、连接和TLS,还是请求发出以后等待响应的时间?

操作方法:

  1. 打开开发者工具并进入Network;

  2. 勾选Preserve log,保留重定向记录;

  3. 需要模拟首次访问时勾选Disable cache

  4. 刷新页面,选择最初的HTML文档请求;

  5. 打开Timing,查看DNS、Initial connection、SSL、Request sent、Waiting和Content Download;

  6. 检查Headers中的状态码、远程地址、缓存状态和重定向位置。

如果DNS、TCP和TLS都很低,而Waiting明显偏高,才更应该把注意力放到CDN处理、回源和服务器准备响应上。

如果所谓“TTFB高”主要耗在DNS或连接阶段,直接优化数据库通常不会有明显帮助。

第四步:通过多地区测试判断是局部问题还是整体问题

本地一次测试无法代表所有用户。CDN会根据地区、运营商和DNS结果调度节点,不同用户可能走完全不同的路径。

可以使用CDNChart网站测速观察多个地区与运营商的解析IP、连接时间、TTFB、总耗时和状态码,重点寻找以下规律:

  • 某个运营商是否普遍偏高;

  • 某个省份是否被调度到较远节点;

  • 国内正常、海外异常,或者反过来;

  • P50正常但P95明显偏高;

  • HIT与MISS是否呈现不同分布;

  • 高峰时段是否比低峰明显变慢。

如果所有地区、所有运营商的动态请求同时变慢,源站或公共回源链路的可能性更高;如果只有某些区域异常,更应该先检查节点调度与区域线路。

不要只看全国平均值。几个表现很好的节点,可能把一个核心运营商的严重异常稀释掉。

第五步:安全地做源站对照测试

源站对照的目的,是尽量绕开CDN边缘层,观察源站在相同Host、路径和TLS条件下的响应,但这个动作需要谨慎。

在你拥有授权、源站允许当前测试IP访问的前提下,可以使用curl --resolve把域名临时指向指定源站IP,同时保留正确的Host和TLS SNI:

curl --resolve www.example.com:443:203.0.113.10 \
  -sS -o /dev/null \
  -w 'status=%{http_code}\nttfb=%{time_starttransfer}\ntotal=%{time_total}\n' \
  https://www.example.com/test.html

这里的203.0.113.10只是文档示例地址,实际使用时替换为自己的测试源站地址。

需要注意:

  • 不要把真实源站IP提交到公开测速平台;

  • 不要为了测试而长期开放源站公网访问;

  • 不要取消“只允许CDN回源IP访问”的安全策略;

  • 优先通过VPN、堡垒机、内网探针或临时白名单测试;

  • 使用只读测试路径,避免触发订单、登录或数据修改;

  • 如果源站本来就禁止直连,直测失败是预期结果,不代表源站宕机。

更理想的做法,是同时在源站反向代理或应用层记录请求处理时间。

例如Nginx日志中的请求时间、上游响应时间,或者应用性能监控中的数据库和外部API耗时。这样可以把“网络等待”和“程序处理”进一步分开。

CDN一侧导致TTFB高,常见原因有哪些?

节点调度不理想

用户没有命中合适的地区或运营商节点,TCP连接和TLS握手会变慢。即使资源最终HIT,首字节仍可能偏高。

可以使用CDN检测工具查看不同解析结果、节点IP和可能使用的CDN,再结合多地区测速判断调度是否合理。

缓存键过度碎片化

如果查询参数、Cookie、Header或设备类型都参与缓存键,同一份内容可能被拆成大量缓存版本。

表面上配置了缓存,实际请求却频繁MISS。

调整前先确认哪些变量确实会改变响应内容。盲目忽略查询参数或Cookie,也可能把不该共享的个性化内容缓存给其他用户。

TTL太短或频繁刷新缓存

缓存有效期过短、发布流程频繁全量刷新,都会增加MISS和回源。

需要根据内容更新频率设置TTL,并优先做精确刷新,而不是每次发布都清空全部缓存。

回源节点与源站距离过远

用户到边缘节点很近,但边缘节点回源需要跨地区甚至跨洲。动态请求和缓存MISS都会为这段路径付出时间。

可以考虑更合理的源站区域、分区域源站、Origin Shield或分层缓存,但要结合一致性、成本和故障切换设计。

边缘安全和计算规则过重

复杂WAF规则、Bot检测、边缘函数、鉴权和多次内部重写可能增加处理成本。

不能为了降低几十毫秒就关闭必要安全能力,但可以检查是否存在重复规则、低效逻辑或不必要的全站执行。

重定向发生在CDN边缘

HTTP跳HTTPS、裸域跳www、语言跳转和路径规范化如果层层叠加,会让用户在真正请求内容前经历多次往返。

目标不是消灭所有重定向,而是避免可以合并的一串跳转。

源站一侧导致TTFB高,常见原因有哪些?

应用工作进程或连接池排队

请求到达服务器后没有立即获得执行资源,只能等待PHP-FPM、Java线程池、Node.js事件循环或数据库连接池。

低峰期正常、高峰期P95突然升高,常见于这种情况。

数据库查询、锁或缓存异常

缺少索引、慢查询、锁等待、缓存击穿和连接池耗尽,都可能把页面首字节拖到几秒。

需要查看具体查询耗时,而不是只看数据库CPU平均值。

外部API拖慢整个页面

支付、库存、推荐、身份验证或第三方数据接口如果采用同步等待,只要其中一个接口变慢,源站就无法及时返回页面。

应设置合理的连接与读取超时,并根据业务设计降级、缓存或异步处理。

服务器资源饱和

CPU不高不代表服务器一定没有瓶颈。

磁盘I/O、内存交换、网络连接数、文件描述符、容器限额和单线程热点都可能造成排队。

检查应覆盖高峰时段和慢请求发生的具体时间,而不是只看一天平均值。

冷启动或运行时初始化

Serverless函数、容器扩容和休眠后的应用实例,首次请求可能需要初始化环境、建立数据库连接或加载依赖,导致少量请求TTFB很高。

这类问题通常更容易出现在P95或P99,而不是P50。

源站缓存没有生效

CDN缓存和源站页面缓存是两层不同的缓存。

即使动态页面不适合放到公共CDN缓存,也可能通过应用缓存、对象缓存或数据库查询缓存降低生成时间。

修复前先确定目标,不要只追求一次最低值

TTFB优化更适合看一组稳定指标:

  • 核心地区及运营商的P50、P95;

  • 静态HIT、MISS和动态请求分别统计;

  • HTTP成功率、超时率和5xx比例;

  • CDN回源比例与缓存命中率;

  • 源站应用处理时间和上游响应时间;

  • 高峰与低峰的差异;

  • 发布或配置变更前后的基线。

如果优化后本地最好成绩从180ms降到160ms,但核心用户的P95仍然超过两秒,实际问题并没有解决。

相反,如果平均值变化不大,但超时和尾部慢请求显著减少,用户体验可能已经得到明显改善。

常见问题

TTFB高一定是服务器配置差吗?

不一定。

浏览器或测速工具记录的TTFB可能包含DNS、连接、TLS、网络往返、CDN处理、回源和源站响应。先拆分各阶段,再判断服务器是否是真正瓶颈。

缓存HIT了,TTFB为什么还很高?

HIT只表示内容由缓存提供,不代表用户到节点的线路一定快。

节点调度、运营商网络、TCP/TLS、边缘安全规则、节点负载和测量口径都可能影响TTFB。

源站直测很快,为什么经过CDN反而慢?

先确认直测位置是否公平。

如果直测机器与源站在同一机房,而CDN回源节点位于外地,两者没有可比性。还要检查回源TLS、连接复用、源站对CDN IP的安全检查和缓存状态。

是不是增加CDN节点就能降低TTFB?

不一定。

节点数量不能替代正确调度、运营商互联、节点容量和回源设计。如果问题发生在源站程序或数据库,增加边缘节点对动态请求帮助有限。

TTFB已经很低,网站为什么仍然打开慢?

TTFB只到“收到第一个字节”为止。后面还有HTML下载、图片、CSS、JavaScript、字体、第三方接口和浏览器渲染。

可以继续参考《Ping很快,网站却很慢?别把延迟当成加载速度》,检查下载与渲染阶段。

到底先联系CDN还是服务器运维?

先准备证据再联系会更有效:同一URL的测试时间、地区、运营商、解析IP、状态码、缓存状态、DNS/TCP/TLS/TTFB、P50/P95,以及源站同期日志。

HIT在特定地区持续偏高,可以先让CDN检查节点和线路;MISS与动态请求普遍偏高,同时源站处理时间也升高,则优先由服务器和应用团队排查。

若源站处理正常、但CDN回源等待明显偏高,再由双方一起核对回源路径与连接策略。

  • TTFB高怎么解决
  • CDN TTFB高
  • 源站响应慢
  • TTFB多少正常
  • 首字节时间高
  • 网站首字节慢
  • CDN回源慢