网站访问速度变慢怎么排查?个人站长从 TTFB 到慢查询的完整思路

先别急着重启,先定位问题

网站变慢是个人站长最常遇到的「玄学」问题:明明什么都没改,怎么就慢了呢?很多人的第一反应是重启服务器、加带宽、上 CDN,结果钱花了问题还在。其实网站变慢从来不是玄学,它一定是某个环节出了状况——网络、DNS、服务器资源、数据库、缓存、代码,总有一环。本文给你一套可以照着做的排查流程:先判断慢的类型,再逐层量化定位,最后针对性解决。

一、先判断「慢」是哪一种

排查前先回答三个问题:

  • 全站都慢,还是只有个别页面慢?全站慢多半是服务器资源或网络问题;个别页面慢则要怀疑页面本身,比如图片太大、插件冲突、SQL 查询太重。
  • 首次访问慢,还是刷新也慢?首次慢通常是缓存未命中或后端处理慢;刷新也慢说明缓存根本没生效,要先查缓存。
  • 你自己慢,还是所有人都慢?换手机流量试试,再让不同地区的朋友访问一下。只有你慢,问题很可能出在你本地网络或 DNS。

这三个问题能帮你把排查范围缩小一大半,避免在错误的方向上浪费几个小时。

二、用 curl 量化 TTFB

不要凭感觉判断「慢」,用数据说话。在本地和服务器上分别执行:

curl -o /dev/null -s -w "DNS:%{time_namelookup}s 连接:%{time_connect}s TLS:%{time_appconnect}s 首字节:%{time_starttransfer}s 总计:%{time_total}s\n" https://你的域名

看几个关键指标:DNS 解析时间异常(超过 0.5 秒)说明 DNS 服务商或本地解析有问题;连接时间异常说明网络链路不通畅;首字节时间(TTFB)异常说明服务器处理慢,这是最需要关注的一项;总时间减首字节时间很长,说明页面体积大或带宽不足。

一个重要的对比技巧:在服务器本机 curl 自己(用内网地址或 127.0.0.1)。如果本机 TTFB 很快、外部访问却很慢,问题在网络层;如果本机也慢,问题在服务器内部——PHP、数据库、磁盘 IO,逐层往下查。

三、浏览器 Network 面板看前端

打开开发者工具切到 Network 面板,正常加载一次页面。重点看几类问题:

  • 有没有单个资源特别大:一张几 MB 的图片没压缩,或上传了原图直接引用,一个页面光图片就拖半天;
  • 静态资源有没有走缓存:第二次加载时图片、JS、CSS 应该返回 304 或直接命中本地缓存,如果全是 200 说明缓存头没配好;
  • 有没有启用压缩:响应头里没有 Content-Encoding: gzip 或 br,说明压缩没开,文本类资源白白多传好几倍体积;
  • 第三方资源拖后腿:统计代码、字体、外链 JS 挂掉或超时,会阻塞页面渲染,这种问题在浏览器里最容易发现。

另外注意首屏渲染:如果页面大量依赖 JS 才能显示内容,或者阻塞渲染的脚本太多,即使服务器响应很快,用户感知依然是慢。把统计代码、广告脚本改成异步加载,首屏速度会有肉眼可见的提升。

四、服务器负载与资源排查

登录服务器,用几条命令快速体检:

uptime                    # 负载,持续超过 CPU 核数就是过载
top -b -n1 | head -20     # 看 CPU 和内存占用最高的进程
free -h                   # 内存和 swap 使用情况
iostat -x 1 3             # 磁盘 IO,%util 长期 90% 以上说明磁盘是瓶颈
df -h                     # 磁盘空间,满了会导致各种诡异故障

常见情况一:负载打满但业务并不忙——很可能被恶意爬虫或采集器刷爆了,去 access log 里按 IP 统计请求数,找出异常来源,配合 Nginx 限流和封禁解决。常见情况二:CPU 长期 100% 且进程名可疑——检查是不是被挖矿程序入侵,用 top 和 ps 结合排查,发现异常进程立刻取证并处理。

五、数据库慢查询排查

很多「页面变慢」的根源在数据库。先打开慢查询日志(以 MySQL 为例):

SET GLOBAL slow_query_log = ON;
SET GLOBAL long_query_time = 2;   # 超过 2 秒的 SQL 记录

然后分析慢查询日志里出现频率高的 SQL,常见原因就三类:

  • 缺索引:WHERE 条件里的字段没有索引,导致全表扫描,数据量一大就慢;
  • 深分页:LIMIT 100000, 20 这种写法,MySQL 要先扫描前 10 万行再丢弃,越翻越慢;
  • 数据膨胀:随着文章和评论增多,以前能跑的数据量现在跑不动了。

对可疑 SQL 执行 EXPLAIN 看执行计划:type 列是 ALL 就说明全表扫描,rows 估算值过大也说明索引没生效。加上合适的索引后,慢查询通常立竿见影。

除了慢查询日志,还可以直接看数据库当前正在做什么:执行 SHOW FULL PROCESSLIST,能看到正在运行的 SQL 和已经执行了多久。如果某条 SQL 反复出现且耗时长,基本就是它在拖慢整个站点;确认无误后用 KILL 终止危险查询,再针对它做索引优化。

六、缓存命中率检查

缓存是网站性能的放大器,但缓存「没命中」等于没有缓存。分层检查:

  • PHP OPcache:在 phpinfo 页面或状态页看命中率,长期低于 90% 说明 opcache 配置需要调整;
  • Redis/Memcached:执行 INFO stats,看 keyspace_hits 和 keyspace_misses,命中率低于 80% 要检查 key 的设计和过期策略;
  • 页面级缓存:Nginx fastcgi_cache 或缓存插件,响应头里一般有 X-Cache: HIT 或 MISS,MISS 比例高说明缓存没生效或一直在过期重建。

一个经典问题:明明开了页面缓存,命中率还是低。常见原因是缓存 key 里带了不稳定的参数,比如时间戳、随机数,或者缓存时间设得太短,页面刚生成就被淘汰,等于每访问一次都回源重建一次。

以 Redis 为例,redis-cli INFO stats 输出的 keyspace_hits 和 keyspace_misses 两个计数器就能算出命中率;PHP 侧如果启用了对象缓存,还可以通过 phpinfo 或调试面板确认缓存是否真的在读,而不只是「配置了」。

七、网络链路与外部因素

如果服务器本机一切正常,但访客就是慢,检查链路:

mtr -rw 目标IP   # 看每一跳的丢包和延迟
dig 你的域名      # 看 DNS 解析结果和耗时

mtr 里某个节点持续丢包或延迟飙升,说明链路绕路或运营商问题,可以考虑换线路或上 CDN 解决;解析耗时异常,考虑换 DNS 服务商,国内可以用阿里云 DNS、腾讯 DNSPod。另外别忘了访客地域:服务器在海外、访客在国内,物理距离摆在那里,加 CDN 是更现实的解法,靠优化服务器本身很难消除跨洋延迟。

八、一套推荐的排查顺序

把上面的方法串成固定流程,下次再遇到就不用慌:

  1. 先量化:curl 记录 TTFB 和总耗时,作为排查基线;
  2. 分内外:服务器本机测一次,区分网络问题和服务器问题;
  3. 查资源:负载、内存、磁盘 IO,排除资源瓶颈和被攻击;
  4. 查数据库:开慢查询日志加 EXPLAIN,处理慢 SQL;
  5. 查缓存:命中率逐层检查,确认缓存真正生效;
  6. 查前端:大资源、压缩、缓存头、第三方脚本;
  7. 改一个变量测一次,不要同时改多个配置,否则出了问题不知道是谁引起的。

这套流程的核心是「用数据代替猜测」。大部分网站变慢问题,都能在这几步里找到答案,真正需要重装系统、换服务器的极少。

常见问题(FAQ)

Q:TTFB 很慢但服务器负载很低,可能是什么原因? A:优先怀疑 PHP-FPM 进程阻塞或慢 SQL,其次检查磁盘 IO——云服务器的突发 IO 可能被打满而 CPU 却闲着。负载低不代表没有瓶颈。

Q:用了 CDN 还是慢怎么办? A:先确认访问是否真的走了 CDN 节点(ping 域名看解析到的 IP),再检查源站是否健康——CDN 回源慢,边缘节点再快也没用。还要看缓存命中率,动态内容没被缓存的话,每次请求都要回源。

Q:这些排查工具需要装很多软件吗? A:curl、top、free、df 是系统自带的;iostat 装 sysstat 包,mtr 装 mtr 包,都是几十 KB 的小工具,装上不亏,排查时能省大量时间。

Q:排查了好几天都没找到原因怎么办? A:回到基线对比:把变化前后的代码提交、配置改动、流量波动列出来,逐项回滚测试。多数「找不到原因」的慢问题,最后都发现是某个不起眼的小变更引起的。

Last modification:August 5th, 2026 at 08:09 am

Leave a Comment