上一篇 下一篇 分享链接 返回 返回顶部

香港服务器晚上变慢,如何从网络、系统和应用层逐步定位原因?

发布人:Minchunlin 发布时间:2026-10-04 17:17 阅读量:4

晚上访问香港服务器时出现页面打开慢、接口超时、SSH 操作卡顿或间歇性 502/504,并不意味着服务器本身一定故障。晚间问题可能来自访问链路拥塞、DNS 或 TCP 建连、Web 入口排队、系统资源耗尽、应用线程池等待,也可能是数据库锁等待或慢查询。定位时不能只看一次 Ping,也不能一上来重启服务器,而应按照“外部链路 → Web 入口 → 系统资源 → 应用服务 → 数据库”的顺序逐层缩小范围。

最有效的做法是先确认影响范围,再用 Ping 和 traceroute 判断链路变化,用 curl 和 Web 日志区分连接慢还是处理慢,随后检查 CPU、内存、磁盘、连接数和应用线程池,最后核对数据库会话、锁等待与查询延迟。每一层都要根据结果决定是否进入下一层,这样才能判断“晚上变慢”究竟是网络问题,还是服务器内部的处理能力在特定时段被占满。

先确认:到底是哪一段变慢

故障排查的第一步不是执行大量命令,而是确定变慢的范围。至少记录以下信息:

  • 变慢开始和结束的大致时间,例如 20:00 至 22:30。
  • 受影响的域名、接口或页面。
  • 是所有访问者都慢,还是某个办公网络、运营商或固定出口慢。
  • 静态文件、健康检查接口和动态业务接口是否同时变慢。
  • 是首次连接慢、等待响应慢,还是响应开始后下载速度慢。
  • 是否伴随 502、504、499、连接超时或服务器负载升高。

可以先从外部访问端执行一次请求耗时拆分。下面命令适用于 Linux、macOS 等包含 curl 的环境,域名和路径需要替换为实际地址:

curl -sS -o /dev/null \
  -w 'dns=%{time_namelookup}s connect=%{time_connect}s tls=%{time_appconnect}s ttfb=%{time_starttransfer}s total=%{time_total}s code=%{http_code}\n' \
  https://your-domain.example/health

各字段的判断方式如下:

指标主要反映变大时优先检查
dns域名解析耗时DNS 响应、解析链路、解析服务
connectTCP 建连耗时路由、丢包、入口连接排队
tlsTLS 握手耗时TCP 稳定性、握手资源、证书链传输
ttfb收到首字节前的等待时间Web 入口、应用、数据库
total完整请求总耗时首字节等待、响应传输和客户端链路

如果 connect 明显上升而 ttfb 正常,优先看网络和 Web 入口;如果连接很快但 ttfb 变成数秒,说明请求已经到达服务器,慢点更可能在 Web 服务、应用或数据库。若 ttfb 正常但 total 很高,则要关注响应体大小、出口带宽和客户端接收速度。

建立一棵原因树

可以把“晚上变慢”拆成五个分支:

建立一棵原因树配图

  1. 访问链路异常:延迟升高、丢包、路由某段拥塞或 TCP 建连困难。
  2. Web 入口排队:监听队列、连接数、工作进程或反向代理上游连接达到瓶颈。
  3. 系统资源紧张:CPU、内存、磁盘 I/O、文件描述符或网络连接被占用。
  4. 应用处理变慢:线程池、任务队列、外部依赖或连接池等待。
  5. 数据库拖慢请求:慢查询、锁等待、连接数不足或磁盘 I/O 增大。

这五个分支可能同时发生。例如晚间访问量增加,先使 Web 连接数上升,再让应用线程池排队,最终表现为数据库连接池耗尽。排查时应记录每一层的时间点,避免把最后看到的异常直接当成根因。

第一层:检查网络链路

用 Ping 判断延迟和丢包趋势

在访问端对服务器 IP 执行连续测试:

ping -c 20 -i 0.2 your.server.ip

Windows 环境可以使用:

ping -n 20 your.server.ip

重点观察:

  • 平均延迟是否比白天明显升高。
  • 最大延迟是否偶发性跳高。
  • 是否存在持续丢包,而不是单个超时。
  • 不同时间段测试结果是否具有重复性。

例如,白天延迟约 25 毫秒,晚间连续多次升至 150 毫秒以上,并伴随 5% 左右丢包,说明链路或入口方向值得优先检查。但 Ping 只能说明 ICMP 报文的往返情况,不能直接证明 HTTP 请求一定慢。部分网络设备会降低或限制 ICMP 优先级,因此 Ping 丢包而网页正常时,不能直接把服务器判定为故障。

反过来,Ping 稳定也不能证明业务正常。应用请求可能在服务器内部等待数据库,或者 HTTPS 已建立但 Web 服务迟迟没有返回首字节。

用 traceroute 观察延迟从哪一跳开始变化

Linux 下可以使用:

traceroute -n -w 1 -q 3 your.server.ip

如果服务器主要提供 HTTPS,也可以在支持 TCP 探测的 Linux 环境中测试 443 端口:

traceroute -T -p 443 -n -w 1 -q 3 your.server.ip

重点不是寻找某一跳出现了一个 *,而是比较多次结果:

  • 前几跳就开始整体升高,可能是访问端出口或接入网络变化。
  • 中间某一跳显示高延迟,但后续各跳恢复,通常不能据此认定该跳转发故障。
  • 从某一跳开始,后续所有跳和最终服务器都持续升高,才更值得关注该段链路。
  • 最终目标地址正常,但中间设备不响应探测,往往只是设备不返回 traceroute 报文。
  • UDP 或 ICMP 探测异常、TCP 443 正常时,不能直接推断 HTTPS 业务不可用。

因此,traceroute 的价值在于观察“延迟变化从哪里开始并是否延续到终点”,而不是简单寻找显示星号的节点。最好分别在白天和晚间执行,并保存时间戳和最终目标的结果。

区分链路慢和服务器出口拥塞

如果外部 Ping、traceroute 和 curl 的连接阶段都变慢,优先处理链路或连接入口问题。如果外部连接正常,但服务器对外发送响应慢,则还要检查服务器自身的网络统计:

ss -s
ip -s link

ip -s link 显示的是累计计数,不能只看一个瞬时值。可以间隔几分钟记录接收、发送、丢弃和错误计数,观察增量是否在晚间明显增加。若系统安装了 sar,还可以查看网卡速率:

sar -n DEV 60 5

这些数据只能说明网卡和连接层面的状态,不能单独证明某个业务接口慢。必须和 curl、Web 日志中的请求耗时结合判断。

第二层:检查 Web 入口是否排队

网络请求到达服务器后,还要经过监听端口、Web 服务和反向代理。以 Nginx 为例,先确认服务状态和实际配置位置,不要直接假定日志一定在某个路径:

systemctl status nginx --no-pager
nginx -T 2>/dev/null | grep -E 'access_log|log_format'
ss -lntp

如果使用的是其他 Web 服务,应使用该服务对应的状态和日志命令。

看访问日志中的耗时字段

如果日志已经记录了 $request_time 和 $upstream_response_time,可以在晚间时间段筛选对应请求。常见含义是:

  • request_time:从接收请求到完成响应的总时间。
  • upstream_response_time:Web 服务等待上游应用返回的时间。
  • 499:客户端提前关闭连接,可能是客户端超时,也可能是上游响应太慢导致用户放弃。
  • 502:上游返回异常、连接失败或响应格式不符合预期。
  • 504:等待上游超过超时时间。
  • 5xx:服务器端处理失败,但仍需结合具体错误日志判断。

如果当前日志没有记录耗时字段,不建议在高峰期直接修改配置。可以先保留现有日志,选择低峰期添加临时字段。参考格式如下:

log_format timing '$remote_addr "$request" $status '
                  'bytes=$body_bytes_sent '
                  'request_time=$request_time '
                  'upstream_time=$upstream_response_time';

access_log /var/log/nginx/access.log timing;

修改前应备份配置,检查语法后再平滑加载:

nginx -t
systemctl reload nginx

如果 nginx -t 未通过,不要执行 reload。回滚时恢复备份配置,再次执行 nginx -t,确认无误后重新加载。配置文件路径和服务名称可能因系统安装方式不同而变化,应以 nginx -T 和实际服务状态为准。

根据两个耗时字段判断位置

可以用下面的逻辑判断:

  • request_time 和 upstream_response_time 都高:应用或数据库处理慢的可能性较高。
  • request_time 高,但 upstream_response_time 较低:可能是客户端接收慢、响应体较大、Web 进程发送排队,或连接层存在问题。
  • 静态文件很快,动态接口很慢:优先检查应用和数据库。
  • 所有静态、动态请求都慢:检查入口连接、系统资源和网络出口。
  • 502/504 在晚间集中增加:检查上游应用是否存活、连接池是否耗尽、应用是否被系统杀掉。
  • 499 增多但服务器端处理时间也变长:客户端超时可能只是结果,根因仍可能在应用或数据库。

监听端口的 Recv-Q 也可作为辅助判断:

ss -lntp

对于监听 socket,Recv-Q 持续较高可能表示已有连接等待 Web 进程接受;对于普通连接,字段含义不同,不能用同一标准解释。若连接数和队列只在访问高峰短时间升高,说明可能存在突发流量或工作进程处理能力不足;若队列持续堆积,则需要继续检查 CPU、I/O 和上游响应时间。

第三层:检查系统资源负载

网络正常、请求确实到达 Web 服务后,下一步是判断服务器是否在晚间被某项资源拖慢。Linux 环境可以先执行一组只读命令:

date
uptime
nproc
vmstat 1 5
free -h
df -h
df -ih

若系统安装了 sysstat,再执行:

iostat -xz 1 5

CPU 高不一定等于 CPU 是根因

uptime 的 load average 应结合 nproc 一起看。负载数值超过 CPU 核数只能说明可运行或等待资源的任务较多,不能简单等同于 CPU 使用率达到 100%。

在 vmstat 中重点关注:

  • r:等待运行的任务数。持续高于可用 CPU 数,说明 CPU 竞争明显。
  • us:用户态 CPU 使用率。
  • sy:内核态 CPU 使用率。
  • wa:等待磁盘 I/O 的时间比例。
  • si、so:交换分区换入换出。持续出现通常说明内存压力较大。

如果 us、sy 较高,应继续查找占用 CPU 的进程;如果 wa 较高,CPU 可能只是等待磁盘,并非真正的计算瓶颈。

ps -eo pid,ppid,comm,%cpu,%mem,stat --sort=-%cpu | head -n 15

检查内存、磁盘和文件系统

free -h 主要看可用内存和 Swap 使用情况。单纯看到系统使用了较多缓存并不代表内存不足,重点是 available 是否持续很低,以及 vmstat 中是否反复出现换入换出。

磁盘方面要同时看空间和 I/O:

  • df -h:检查磁盘容量是否接近用尽。
  • df -ih:检查 inode 是否用尽。小文件数量过多时,容量未满也可能无法创建新文件。
  • iostat -xz:关注 await、%util 和读写吞吐。

典型判断方式是:

  • await 持续升高,同时 wa 较高:请求可能在等待磁盘。
  • 磁盘容量或 inode 接近耗尽:日志写入、临时文件和数据库操作可能失败。
  • CPU、内存、磁盘均正常,但应用请求仍慢:继续转向线程池、连接池和数据库等待。
  • 只有晚间某个时间段 I/O 突然升高:检查备份、日志压缩、批量导入、报表生成等定时任务。

可以查看系统定时器,但不要在故障期间随意删除或禁用任务:

systemctl list-timers --all
crontab -l

如果确认某项任务与慢请求时间完全重合,应先保留任务配置和执行记录,再评估错峰、限速或调整执行方式。直接停止备份、日志轮转或数据库维护任务,可能造成数据保护和日志完整性问题。

第四层:检查应用服务

当 Web 日志显示 upstream_response_time 较高,而系统资源又没有明显耗尽时,问题通常位于应用内部。常见原因包括:

  • 工作线程或协程数量不足,请求在队列中等待。
  • 数据库连接池耗尽,应用线程等待可用连接。
  • 调用外部服务的超时时间过长,少量慢请求占满工作线程。
  • 晚间批处理、报表或定时任务与在线请求争用资源。
  • 垃圾回收、缓存失效或大量缓存同时重建。
  • 应用进程数量减少、进程重启或健康检查异常。

如果应用由 systemd 管理,可按时间查看应用日志:

journalctl -u your-app.service \
  --since "today 20:00:00" \
  --until "today 22:00:00" \
  --no-pager

your-app.service 需要替换为实际服务名。若应用不是 systemd 服务,应根据实际日志位置查找,不要直接套用路径。

应用层最好同时记录以下指标:

指标判断价值
请求总量和成功率判断是否由流量变化触发
P50、P95、P99 延迟识别少数慢请求还是整体变慢
活跃线程、等待线程判断工作线程是否排队
应用连接池使用率判断数据库或外部服务连接是否不足
队列长度和处理速率判断任务是否积压
重启次数和异常数量判断进程是否不稳定

不要只看平均响应时间。假设平均值为 300 毫秒,但 P99 已达到 8 秒,用户仍会明显感知到卡顿。晚间排查时,应把访问日志、应用日志和系统指标统一到同一时区,至少精确到分钟,必要时精确到秒。

第五层:检查数据库等待

动态请求普遍变慢时,数据库是常见的深层原因,但“数据库连接数高”本身不能直接证明数据库故障。需要同时观察:

  • 活跃会话数和正在执行的会话数。
  • 慢查询数量及其 P95、P99 延迟。
  • 锁等待和事务持续时间。
  • 数据库 CPU、磁盘 I/O 和缓存命中情况。
  • 应用连接池是否已用尽。
  • 是否有晚间批量写入、统计或备份任务。

以 MySQL 或 MariaDB 为例,下面是只读查看方式。使用登录配置保存凭据,避免把密码直接写在命令行中:

mysql --login-path=local --batch --raw -e \
"SHOW GLOBAL STATUS LIKE 'Threads%';
 SHOW FULL PROCESSLIST;"

查看 InnoDB 状态:

mysql --login-path=local -e "SHOW ENGINE INNODB STATUS\G"

这些命令需要相应的数据库权限,且 SHOW FULL PROCESSLIST 可能包含业务 SQL 内容,应注意访问权限和敏感信息保护。重点不是看到某个连接数就下结论,而是将数据库状态与应用日志中的等待时间对应起来。

例如:

  • Threads_connected 高,但 Threads_running 低,可能只是连接保持较多,不一定是执行瓶颈。
  • Threads_running 长时间升高,且应用请求同步变慢,说明数据库处理或锁等待值得深入检查。
  • 应用显示“等待数据库连接”,而数据库本身活跃查询不多,可能是连接池配置、连接泄漏或连接未及时释放。
  • 数据库 I/O 延迟和服务器 iowait 同时上升,说明慢点可能位于存储等待。
  • 只有少数 SQL 变慢,应使用执行计划和慢查询样本定位,不要盲目修改全部查询或索引。

生产环境不要随意执行终止会话、批量更新、重建索引等操作。涉及 SQL、锁和索引的变更,应先备份相关配置或数据库对象信息,评估事务影响,在低峰或维护窗口执行,并准备撤销或恢复方案。

用结果矩阵锁定根因

下面的矩阵适合在记录数据后进行交叉判断:

现象其他观察更可能的方向下一步
Ping 和 TCP 建连在晚间同时升高Web ttfb 也升高访问链路或入口连接对比多次 traceroute、检查连接队列
Ping 稳定ttfb 从数百毫秒升至数秒Web、应用或数据库查看 request_time、upstream_time
静态资源正常动态接口慢应用或数据库检查线程池、连接池和慢查询
所有请求都慢CPU 或 iowait 升高系统资源查看进程、磁盘和定时任务
request_time 高、upstream_time 低响应体较大或客户端中途断开发送链路、客户端接收或 Web 排队查看 499、响应大小和连接统计
502/504 集中出现应用重启或连接池耗尽Web 到应用的上游链路查看应用日志和进程状态
数据库活跃查询和锁等待升高应用线程等待数据库连接数据库处理能力或事务争用查慢查询、锁等待和事务时长

例如,假设晚间测试得到以下结果:Ping 仍约 25 毫秒,connect 约 40 毫秒,但 ttfb 从 0.3 秒变成 4 秒;同时 Nginx 的 upstream_response_time 接近 3.8 秒,应用日志显示大量数据库连接池等待。这组证据就不支持“线路变慢”的判断,应该继续查数据库连接、慢查询和锁等待。

用结果矩阵锁定根因配图

另一个示例是 Ping 在白天约 25 毫秒、晚间升至 150 毫秒,traceroute 从某一段开始到最终服务器都同步升高,服务器本地访问健康检查接口仍很快。此时更接近访问链路拥塞,继续调整应用线程数通常不会解决外部用户的连接延迟。

处理和验证:一次只改变一个变量

定位到方向后,不建议先重启整台服务器。重启可能暂时清空连接和缓存,却会丢失现场信息,也无法证明根因已经消失。更稳妥的处理方式是:

  1. 先保存故障时间段的 Ping、traceroute、curl、访问日志和系统指标。
  2. 确认是链路、入口、资源、应用还是数据库中的哪一层异常。
  3. 优先采用低风险措施,例如错开批处理、降低非关键任务并发、恢复异常应用进程。
  4. 配置变更前备份文件,检查语法,通过平滑加载验证,避免直接覆盖生产配置。
  5. 数据库查询、索引和事务调整应在明确影响范围后执行,并准备回滚或恢复方案。
  6. 修改后继续使用同一接口、同一测试方式和相近时间段进行对比。

恢复验证不能只看一次页面是否打开,而应至少确认:

  • curl 的 connect、ttfb 和 total 是否恢复到平时范围。
  • 5xx、499 和超时比例是否下降。
  • Nginx 的 P95、P99 请求耗时是否恢复。
  • CPU、内存、iowait、磁盘等待和连接队列是否稳定。
  • 应用线程池、数据库连接池是否仍在持续积压。
  • 业务功能、写入操作和后台任务是否出现副作用。

把晚高峰变成可观测事件

如果问题只在晚上出现,单次人工排查往往难以捕获现场。建议围绕同一时间轴持续记录以下监控点:

  • DNS 解析耗时、TCP 建连耗时、TLS 握手耗时。
  • HTTP 首字节时间、总响应时间、P95/P99 延迟。
  • 2xx、4xx、5xx、499、502、504 比例。
  • 入站和出站流量、连接数、监听队列。
  • CPU 用户态、内核态、负载、iowait。
  • 可用内存、Swap 换入换出、磁盘空间和 inode。
  • 应用线程池、任务队列和数据库连接池。
  • 数据库活跃会话、锁等待、慢查询和磁盘延迟。
  • 晚间定时任务的开始时间、持续时间和资源使用量。

参考阈值只能作为告警起点,不能脱离业务基线直接判定故障。例如,连续多个采样周期出现明显丢包、ttfb 超过平时数倍、P99 持续高于业务可接受范围,或数据库连接池长期接近上限,都比单个瞬时峰值更有诊断价值。

这样处理后,“香港服务器晚上变慢”就不再是一个笼统现象,而能被拆解为可验证的证据链:链路是否变长、请求是否在 Web 入口排队、系统是否缺少资源、应用是否等待线程或连接、数据库是否出现锁和查询延迟。只要保留晚间现场数据,并在每次变更后进行同口径验证,通常可以较快确定真正的瓶颈位置,也能为下一次高峰期建立可复用的判断依据。

目录结构
全文