「站有点慢」是运维里最难查的一类反馈,因为它没有报错,只有一句感觉。可感觉是可以拆的:一次页面请求,时间只会落在四段——解析域名、建连接、握手加密、等服务端把页面算完,最后才是传字节。哪段最长,改法就完全不同。
这篇拿本站当样本,把首页量了十七遍,又把同一台机器上的静态文件量了五遍做对照,最后清点了一遍资源。结论先说:首字节里约 430 毫秒花在服务端每次重算,前端请求不多但图片合计 3.76 MB,两半各占一头,而且要用两种完全不同的手段去治。
四段时间:下载只用了 8 毫秒,剩下都在等
curl -w 能直接吐出五个时间戳,相减就是四段。命令不长,谁都能在自己站上跑:
curl -s -o /dev/null -H 'Accept-Encoding: gzip, br'
-w 'dns=%{time_namelookup} conn=%{time_connect} tls=%{time_appconnect} ttfb=%{time_starttransfer} total=%{time_total} bytes=%{size_download}n'
https://www.618a.com/
十七次采样的中位数是这样:TCP 连接 39 毫秒,握手到 107 毫秒(即 TLS 本身约 67 毫秒),首字节 536 毫秒,全部传完 545 毫秒。也就是说从握手结束到第一个字节,中间空了 429 毫秒;而 28 KB 的压缩 HTML 传下来只用 8 到 10 毫秒。
这段等待最容易误判。浏览器里感觉「加载慢」,多数人第一反应是怪带宽、怪机房线路,可这一项在总时间里连百分之二都不到。真正花时间的是服务端把那 137 KB 的原始 HTML 一字节一字节算出来的过程。
同一台机器,静态文件只要 41 毫秒
要证明慢在 PHP 而不是慢在服务器,最简单的办法是找一个不经过 PHP 的地址做对照。robots.txt 就够用:同一个域名、同一个 nginx、同一张证书,五次采样里 TLS 结束到首字节只用了 41 毫秒。
再把四种页面类型各量五遍,服务端耗时(首字节减去 TLS 结束)是这样:首页 429 毫秒、长文章页 379 毫秒、短文章页 362 毫秒、分类页 346 毫秒。
这组数字有两个意思。一是同样的机器、同样的网络,静态文件 41 毫秒、WordPress 页面 350 到 430 毫秒,差出来的近 400 毫秒全是 PHP 与主题的固定开销。二是四种页面的差距只有 80 毫秒——分类页要跑文章循环、首页要跑幻灯片和五套场景组件,都只差这么点,说明瓶颈不在某一条慢查询,而在「每次请求都要把整个页面从头渲染一遍」这件事本身。

响应头也印证了。首页返回里没有 Cache-Control,只有 Transfer-Encoding: chunked——服务器边算边发,每次访问都是完整的一次动态生成。静态资源那边反倒配好了:max-age=43200 加 ETag,十二小时不回头问。协议层没拖后腿,ALPN 协商到 h2,Alt-Svc 已把 h3 广播出去。
前端请求只有 33 个,但图片是 3.76 MB
清点首页资源:40 个请求、33 个唯一地址,其中 23 个是 CSS 与 JS(14 个样式表、9 个脚本),10 个是图片位图 8 张。HTML 压缩后 28 KB,gzip 已开。这个数量对 WordPress 站来说很干净,问题不在请求数。
体积才是问题。8 张图合计 3.76 MB,其中四张 PNG 分别是 1153 KB、1042 KB、737 KB、694 KB,加起来 3.55 MB,占了首页图片总量的 94%。这四张都是封面——用真实照片打底、底部压一条字幕条的那种。照片存 PNG,是最贵的存法:PNG 是无损格式,它老老实实把每个像素的噪点都记下来,而人眼根本看不出差别。
同一张 1200×630 的封面,我把三种格式跑了一遍:PNG 原图 1153.5 KB,转 JPEG 质量 85 后 172.9 KB,转 WebP 质量 82 后 125.9 KB。体积掉到 15% 和 11%,肉眼看不出区别。

这 3.76 MB 全放在独立图床上,不走主站,所以不受主站 PHP 拖累——但也拿不到主站任何一条缓存策略的保护,换台设备访问就得重新下一遍。
三条改法,和一条别做
先换封面格式。 最大的几张是同一批模板生成的(1200×630、照片打底、底部字幕条),批量转 JPEG 质量 85 就够,单张从 1 MB 级降到 170 KB 级,首页图片总量从 3.76 MB 掉到 0.6 MB 左右。不用改代码、不用动缓存,收益最直接。
再考虑页面缓存。 服务端那 430 毫秒只有缓存能吃:静态文件已经证明这台机器本身很快,慢的是每次都重算。要注意首页有动态成分(幻灯片数据、场景组件由服务端渲染),不能整页无脑缓存,得把那几块排除或用片段缓存。这一项收益最大,风险也最大,建议先在文章页试。
顺手合并样式表。 14 个 CSS 全在 head 里,都是渲染阻塞资源。h2 下并发不是问题,但 14 个文件就是 14 次往返加 14 份解析开销,合到 1 到 2 个能省几十毫秒——加分项,不是主要矛盾。
别去调那两个参数。 流传很广的「加大 realpath_cache_size、开 skip_name_resolve」在本站实测过,一个没效果、一个反而更慢。这类参数在别的站可能有用,但这个环境里别重复试。
边界
所有数据来自本机单点测量,用 --resolve 直连源站 IP,DNS 那段被抹掉了——真实用户还得再加一次解析。站点没有 CDN、也没有页面缓存,所以这组数字是「裸源站」的成本,上 CDN 之后首字节会是另一回事。另外 TTFB 有抖动:十七次里最快 499 毫秒、最慢 658 毫秒,差 159 毫秒,说明服务端高负载时会排队——这也是缓存比微调更值得做的原因。
一、一手信息
- 本站首页与文章页实时响应头(
Cache-Control、Transfer-Encoding、Alt-Svc、Set-Cookie的取值):https://www.618a.com/ - 本站
robots.txt(静态文件对照组的取样地址):https://www.618a.com/robots.txt - curl 官方文档·
-w变量表(time_namelookup、time_connect、time_appconnect、time_starttransfer、time_total的定义):https://curl.se/docs/manpage.html#-w - NGINX 官方文档·
ngx_http_fastcgi_module(fastcgi_cache相关指令,页面缓存一节的依据):https://nginx.org/en/docs/http/ngx_http_fastcgi_module.html
二、媒体报道
- web.dev《Time to First Byte (TTFB)》(首字节时间的构成与好坏分界的通行口径):https://web.dev/articles/ttfb
- MDN《Cache-Control》(
max-age、no-store等指令语义,判读响应头的依据):https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control - Cloudflare 学习中心《What is HTTP/2?》(多路复用与渲染阻塞资源的关系):https://www.cloudflare.com/learning/performance/http2-vs-http1.1/
三、其他
- libwebp 官方文档(WebP 编码质量参数与体积关系)
- Pillow 文档 JPEG
quality与optimize参数说明
本文为本站实测记录,测法与命令已完整给出,可在任意站点复现;不同机房、不同网络下的绝对值会有差异,可比的是四段时间的相互比例。
相关阅读
- 用八条 curl 摸了一遍自家的站:默认配置会自己交出哪些东西:同一个栏目里「查漏」的那一篇
- 服务器运维:本栏目往期实测,服务端变慢的另一种成因
- 建站实战:子主题改造、雷达与运维记录
原创声明:本文由 618A 情报站整理撰写,基于公开信息与实测记录,转载请注明出处并保留原文链接。