"网站好慢"是最模糊的故障描述。慢可能发生在任何一环:本地网络、DNS、服务器带宽、Nginx、PHP、数据库、前端资源、第三方接口……
这篇给一套自顶向下的定位流程,每一步都有可执行命令,帮你把"慢"变成具体的数字和具体的环节。
排到最后如果是带宽或配置瓶颈,就该升级了。财富云计算 提供云服务器与带宽升级选项;内网服务、游戏服务端可选 NAT 型(无独立公网 IP,价格比独立 IP 机型省一半以上)。
一、先量化:到底慢在哪一步
用 curl 分解耗时
curl -o /dev/null -s -w '
DNS 解析: %{time_namelookup}s
TCP 连接: %{time_connect}s
TLS 握手: %{time_appconnect}s
开始传输: %{time_starttransfer}s ← 首字节时间(TTFB)
总耗时: %{time_total}s
下载速度: %{speed_download} B/s
HTTP 状态: %{http_code}
' https://example.com输出示例:
DNS 解析: 0.012s
TCP 连接: 0.145s
TLS 握手: 0.302s
开始传输: 1.850s ← TTFB 很高,问题在服务端
总耗时: 1.920s
下载速度: 125000 B/s
HTTP 状态: 200怎么读:
| 指标 | 偏高说明 |
|---|---|
time_namelookup 大 | DNS 慢,换 DNS 或检查解析 |
time_connect 大 | 网络链路差、跨运营商、服务器远 |
time_appconnect 大 | TLS 握手慢,检查证书链、OCSP |
time_starttransfer(TTFB)大 | 服务端处理慢(PHP/数据库/程序逻辑) |
time_total - time_starttransfer 大 | 内容下载慢(大文件、带宽小) |
speed_download 小 | 带宽瓶颈 |
经验阈值(国内访问):
- DNS < 50ms
- TCP < 100ms(同城)/ < 200ms(跨省)
- TTFB < 500ms 算不错,> 2s 明显有问题
- 首屏加载 < 2s
用浏览器开发者工具
F12 → Network → 刷新页面:
- 哪个请求最慢(瀑布图一眼看出)
- Waterfall 各阶段:Queueing / Stalled / DNS / SSL / Request sent / Waiting(TTFB) / Content Download
Waiting长 = 服务端慢Content Download长 = 资源大或带宽慢Stalled长 = 浏览器并发限制或连接排队
二、排除本地因素
先确认不是你自己网络的问题:
# 1. 换个网络(手机 4G)试试
# 2. 多地 ping
ping example.com -c 10
# 3. 看网络链路哪一跳慢
mtr example.com
traceroute example.com
# 4. 换 DNS 对比
curl --resolve example.com:443:1.2.3.4 https://example.com -o /dev/null -w "%{time_starttransfer}\n"在线多地测速:
- https://www.17ce.com (国内多节点,很实用)
- https://www.webpagetest.org (全球 + 详细瀑布图)
- https://tools.pingdom.com
如果只有你慢、其他地方正常 → 是本地网络问题,不用折腾服务器。
三、服务端排查:按层拆
第 1 层:服务器资源
uptime # 负载
free -h # 内存
df -h # 磁盘
top # 谁在吃资源
iostat -x 1 # 磁盘 IO
iftop # 带宽详细排查见本站《服务器资源排查:CPU / 内存 / 磁盘 / 带宽》。
快速判断:
- 负载高 +
wa高 → 磁盘 IO 瓶颈(数据库在拼命读盘) - 内存 available 接近 0 + swap 在用 → 内存瓶颈,会非常慢
- 带宽跑满 → 看是不是被盗链或被攻击
第 2 层:Nginx
看访问日志里哪些请求慢:
先改日志格式加上耗时(在 nginx.conf 的 http 块):
log_format timed '$remote_addr [$time_local] "$request" $status '
'$body_bytes_sent rt=$request_time urt=$upstream_response_time '
'"$http_referer" "$http_user_agent"';
access_log /var/log/nginx/access.log timed;nginx -t && systemctl reload nginx找出最慢的请求:
# 按 $request_time 排序(awk 取对应字段,按你的日志格式调整)
awk '{print $NF, $0}' /var/log/nginx/access.log | sort -rn | head -20检查 Nginx 状态:
systemctl status nginx
tail -100 /var/log/nginx/error.log常见:
worker_connections are not enough→ 调大upstream timed out→ 后端慢connect() failed→ 后端挂了
第 3 层:PHP-FPM(动态站点的头号嫌疑)
开启慢日志:
nano /etc/php/8.2/fpm/pool.d/www.confslowlog = /var/log/php-fpm/slow.log
request_slowlog_timeout = 2smkdir -p /var/log/php-fpm
systemctl restart php8.2-fpm
tail -f /var/log/php-fpm/slow.log慢日志会打印出具体哪个 PHP 文件的哪一行慢,直接定位到代码。
检查 FPM 是否在排队:
# 开启状态页
# www.conf 里:pm.status_path = /phpfpm-status
# Nginx 里配一个 location 访问它
curl http://127.0.0.1/phpfpm-status关注:
listen queue: 0 ← 大于 0 说明请求在排队,进程不够
active processes: 5
max active processes: 10 ← 经常打满说明要加进程
max children reached: 3 ← 大于 0 说明进程数不够,请求被拒绝
slow requests: 12 ← 慢请求数listen queue 或 max children reached 大于 0 → 调大 pm.max_children(注意内存够不够)。
OPcache 一定要开:
php -m | grep -i opcache # 看看有没有
apt install php-opcache -y没有 OPcache 的 PHP,每次请求都要重新编译脚本,性能差好几倍。
第 4 层:数据库
MySQL 慢查询日志:
nano /etc/mysql/mysql.conf.d/mysqld.cnfslow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1 # 超过 1 秒记录
log_queries_not_using_indexes = 1systemctl restart mysql分析:
# 直接看
tail -100 /var/log/mysql/slow.log
# 用 mysqldumpslow 汇总
mysqldumpslow -s t -t 10 /var/log/mysql/slow.log # 最耗时的 10 条
mysqldumpslow -s c -t 10 /var/log/mysql/slow.log # 出现最多的 10 条
# 或用 pt-query-digest(更专业)
pt-query-digest /var/log/mysql/slow.log实时看正在执行的慢 SQL:
SHOW PROCESSLIST;
-- 或
SELECT * FROM information_schema.PROCESSLIST
WHERE COMMAND != 'Sleep' AND TIME > 2 ORDER BY TIME DESC;最常见的数据库慢原因:
- 没加索引 →
EXPLAIN SELECT ...看是否全表扫描 - 索引失效(函数包裹、
LIKE '%xx'、类型不匹配、隐式转换) - 查询返回太多行(没分页、
SELECT *) - 联表过多或写法糟糕
- 锁等待(长事务、MyISAM 表锁)
- buffer pool 太小(
innodb_buffer_pool_size,建议设为内存的 50~70%)
-- 加索引
ALTER TABLE posts ADD INDEX idx_created (created_at);
-- 看表状态
SHOW TABLE STATUS;
-- 看索引
SHOW INDEX FROM posts;第 5 层:外部依赖
你的程序可能调用了第三方 API(支付、地图、短信、统计),它们慢会拖垮整站。
# 测试第三方接口耗时
curl -o /dev/null -s -w "%{time_total}\n" https://api.third.com/xxx
# 看服务器上的外部连接
ss -tnp | grep -v "127.0.0.1"解决:加超时(别无限等待)、加缓存、异步化。
四、前端层面(资源大、请求多)
服务端 TTFB 很快,但页面还是要很久才出来 → 是前端问题。
检查清单
- [ ] 图片有没有压缩(一张 3MB 的 PNG 就是几秒)
- [ ] 图片格式(用 WebP,体积能小 30~70%)
- [ ] 有没有开启 Gzip / Brotli
- [ ] JS/CSS 有没有合并压缩
- [ ] 有没有加载不必要的第三方脚本(统计、广告、社交插件)
- [ ] 字体文件是否过大(中文字体子集化很重要)
- [ ] 有没有用 CDN
- [ ] 资源有没有缓存头
实操
# 检查是否开启压缩
curl -H "Accept-Encoding: gzip" -I https://example.com | grep -i "content-encoding"
# 检查缓存头
curl -I https://example.com/style.css | grep -i cache
# 看资源大小
curl -o /dev/null -s -w "%{size_download}\n" https://example.com/big.jpgNginx 开启缓存头:
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2)$ {
expires 30d;
add_header Cache-Control "public, immutable";
}图片优化工具:
# 批量压缩 jpg
apt install jpegoptim -y
jpegoptim --max=85 *.jpg
# 批量压缩 png
apt install optipng -y
optipng -o2 *.png
# 转 webp
apt install webp -y
cwebp -q 80 input.jpg -o output.webp五、网络与带宽层
检查带宽是否跑满
iftop -i eth0
sar -n DEV 1# 统计当天流量
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -20
# 看哪个 IP 请求最多、哪个资源流量最大异常情况:
| 现象 | 原因 | 处理 |
|---|---|---|
| 某个 IP 请求量巨大 | CC 攻击 / 爬虫 | 封 IP、限速 |
| 图片被盗链 | Referer 异常 | 加防盗链 |
| 大文件被反复下载 | 被盗链/没缓存 | CDN、限速 |
| 无异常但带宽满了 | 真流量大 | 升级带宽 |
限速与防盗链配置:
# 防盗链
location ~* \.(jpg|png|gif|mp4)$ {
valid_referers none blocked server_names *.example.com;
if ($invalid_referer) { return 403; }
}
# 单连接限速
location /download/ {
limit_rate 500k;
}
# 限制单 IP 并发与请求频率(防 CC)
limit_req_zone $binary_remote_addr zone=req_limit:10m rate=10r/s;
limit_conn_zone $binary_remote_addr zone=conn_limit:10m;
server {
limit_req zone=req_limit burst=20 nodelay;
limit_conn conn_limit 20;
}六、DNS 层
dig example.com +short
dig example.com | grep "Query time"Query time 超过 100ms 就偏慢。
优化:
- 换更快的 DNS 服务商(DNSPod、阿里云 DNS、Cloudflare)
- TTL 设大一些(3600+),减少查询次数
- 如果用户遍布全国/全球,用支持分线路解析的 DNS(电信走电信 IP、联通走联通 IP)
- 检查是否有 CNAME 链过长
DNS 预解析(前端优化):
<link rel="dns-prefetch" href="//cdn.example.com">七、性能优化的常规手段(按性价比排序)
| 手段 | 效果 | 成本 |
|---|---|---|
| 开启 OPcache | ⭐⭐⭐⭐⭐ | 装个包 |
| 开启 Gzip/Brotli | ⭐⭐⭐⭐ | 几行配置 |
| 数据库加索引 | ⭐⭐⭐⭐⭐ | 一条 SQL |
| 静态资源缓存头 | ⭐⭐⭐ | 几行配置 |
| 图片压缩 + WebP | ⭐⭐⭐⭐ | 批量工具 |
| 页面缓存(Nginx proxy_cache) | ⭐⭐⭐⭐⭐ | 中等 |
| Redis/Memcached 缓存查询结果 | ⭐⭐⭐⭐ | 中等 |
| CDN 加速 | ⭐⭐⭐⭐ | 按流量付费 |
| 升级服务器配置 | ⭐⭐⭐ | 花钱,最直接 |
| 前后端分离 / 静态化 | ⭐⭐⭐⭐ | 重构成本高 |
最推荐先做的三件事:OPcache、数据库索引、静态资源缓存。投入极小,收益极大。
八、排查流程图
网站慢
│
├─ curl -w 分解耗时
│ ├─ DNS 慢 → 换 DNS
│ ├─ 连接慢 → 网络链路 / 换机房 / 上 CDN
│ ├─ TTFB 慢 → 服务端问题 ↓
│ └─ 下载慢 → 资源太大 / 带宽小 → 压缩 + CDN
│
└─ TTFB 慢(服务端)
├─ top / free / iostat → 资源瓶颈?
│ ├─ CPU 高 → 查进程 → 程序问题或攻击
│ ├─ 内存满 → 加内存或限流
│ ├─ IO 高 → 数据库在疯狂读盘 → 加索引/加内存
│ └─ 带宽满 → 查流量来源
├─ PHP 慢日志 → 定位到具体文件行
├─ FPM 状态页 → 进程不够?调 pm.max_children
├─ MySQL 慢日志 → 定位慢 SQL → EXPLAIN → 加索引
├─ Nginx error.log → 后端超时?502/504?
└─ 第三方 API → 加超时/缓存九、建立监控,别等用户说
# 简单的定时探测(记录 TTFB)
*/5 * * * * curl -o /dev/null -s -w "%{http_code} %{time_starttransfer}\n" https://example.com >> /var/log/site-perf.log更完整的方案见本站《游戏服务器监控与告警实战》,Netdata 一行命令就能装好,能实时看到所有指标。
告警阈值建议:
- TTFB > 2s 持续 5 分钟 → 告警
- HTTP 状态码非 200 → 立即告警
- 磁盘 > 85% → 告警
- 带宽 > 80% → 告警
排查到最后如果是带宽或配置瓶颈,就该考虑升级了。财富云计算 的云服务器支持按需升级 CPU、内存与带宽,也可以先做快照再升级,风险可控。做内网服务、测试环境、游戏服务端推荐 NAT 型(无独立公网 IP,价格比带独立 IP 机型省一半以上),省下的预算投到内存和带宽上更实在。
相关阅读:
- 《服务器资源排查:CPU / 内存 / 磁盘 / 带宽》
- 《Nginx 反向代理与多站点配置》
- 《服务器备份与快照策略》
延伸阅读
- 网站环境怎么选:LNMP 手动 / 宝塔面板 / Docker / 云开发
- 问卷表单系统搭建:SurveyKing / Formbricks,数据自己收
- 图床搭建:Lsky Pro / Lychee,自托管图片托管方案
- 邮件列表搭建:listmonk 自托管 Newsletter,把读者握在自己手里
- 文档站点搭建:MkDocs / VuePress / Docsify,产品文档与技术手册方案
- RSS 阅读器搭建:FreshRSS 自托管,把信息流拿回自己手里
- 短链接服务搭建:Shlink 自托管,链接数据自己掌握
- 网站状态监控页搭建:Uptime Kuma,服务器挂了第一时间知道

[...]动态: www.example.com → 源站(只开 80/443 给 CDN)WordPress/Typecho 都有 CDN 插件,一键改静态资源地址,配合网站图片优化效果更明显。速度测试方法见网站速度测试工具与方法。CDN 是性价比最高的网站优化:一顿饭钱让全国访问都快一倍,还能藏住源站。配好缓存策略 + 源站保护,就是又安全又快的正经架构。需要现成的游戏云服务器,可以看看财富云计算:一[...]
2026-10-15 回复
[...]lighthouse https://你的域名 --throttling-method=simulate重点看瀑布图(Network 面板):哪个资源最大、哪个阻塞渲染、哪个 TTFB 长。常见元凶排序:没压缩的大图(>500KB 的 banner)未缓存的第三方脚本(统计、客服、广告)阻塞渲染的同步 JS慢 TTFB(服务端/数据库慢)针对性优化见网站图片与静态资源优化和网站打开慢排查流程[...]
2026-10-15 回复
[...]netsh advfirewall firewall add rule name="GameRange" dir=in action=allow protocol=UDP localport=26901-26903完整的 Windows 环境准备(远程桌面连接、运行库安装、SteamCMD 用法、开机自启、8 个常见坑)见:《Windows 云服务器开服通用前置教程》→ htt[...]
2026-10-18 回复