日本服务器部署网站或API访问变慢,如何按CPU、内存和网络指标定位瓶颈

日本服务器上部署网站或 API 后出现访问变慢,不能只看 CPU 是否“跑满”。应先把一次请求拆成 DNS、TCP 连接、TLS、服务器接收、应用处理、数据库查询和响应传输几个阶段,再将这些阶段与 CPU、内存、磁盘、网络指标对应起来。
直接判断时可遵循这条路径:curl 的连接时间和首字节时间明显升高,先查网络或服务端排队;CPU 用户态持续升高,重点查应用计算和进程并发;内存可用量下降并伴随交换,重点查内存压力;磁盘等待升高,重点查日志、数据库或文件读写;网络丢包、错误或重传增加,重点查网卡和链路;如果系统指标正常而接口仍慢,则继续检查应用队列、连接池、慢查询和锁等待。
如果你同时在判断“日本服务器适合部署外贸游戏、API 还是网站?按延迟需求判断”,也应先完成下面的性能定位,再决定是否调整部署方式。不要在尚未确认瓶颈前直接增加进程、修改内核参数或重启全部服务。
先固定目标和前置条件
本文中的命令以常见 Linux 环境为例,部分服务检查以 Nginx 和 systemd 为例。实际执行前应确认:
- 拥有服务器登录权限,以及读取系统指标、查看服务日志的权限。
- 已知网站或 API 的只读测试地址,测试请求不会创建订单、写入数据或触发真实业务。
- 已记录变更前的访问延迟、错误率、并发量和服务器指标。
- 知道应用服务、Nginx 配置和日志的大致位置,不直接猜测路径。
- 已确认当前是否处于业务高峰,避免把正常流量波动误判为故障。
- 已准备配置备份和回滚方式,尤其是涉及 Nginx、应用并发数、连接池或服务重载时。
网站、API 和实时游戏对指标的关注点不同,但定位方法可以统一:
| 业务类型 | 优先观察的延迟表现 | 需要重点排查的指标 |
|---|---|---|
| 网站 | 首字节时间、静态资源响应时间、页面整体加载时间 | 网络连接、Nginx 排队、CPU、磁盘和缓存命中情况 |
| API | 单接口延迟分位数、超时率、5xx 错误率 | 应用线程或协程排队、数据库连接池、慢查询、内存压力 |
| 外贸游戏 | 长连接稳定性、延迟抖动、丢包和重传 | 网络错误、连接数、事件循环 CPU、内存回收和应用队列 |
平均响应时间不能代表全部用户体验。API 和游戏尤其要关注高分位延迟、超时和连接中断;网站则要区分首字节慢和响应内容传输慢。
现状核对:先确认慢在请求的哪一段
1. 用分段时间测量替代“感觉变慢”
在服务器外部或与用户接近的测试位置,对同一个只读地址连续执行多次请求。将示例地址替换为实际健康检查接口、静态页面或不会产生副作用的 API:
URL='https://example.com/health'
for i in 1 2 3 4 5; do
curl -sS -o /dev/null \
-w "dns=%{time_namelookup}s connect=%{time_connect}s tls=%{time_appconnect}s starttransfer=%{time_starttransfer}s total=%{time_total}s code=%{http_code}\n" \
"$URL"
done
各字段可按以下方式判断:
time_namelookup较高:先核对域名解析和客户端到解析服务的耗时。time_connect较高:检查 TCP 建连、监听队列、网络路径或服务器接收能力。time_appconnect较高:HTTPS 建连阶段耗时,检查 TLS 处理、CPU 压力和连接复用情况。time_starttransfer较高而连接时间正常:请求已经到达服务器,但应用、数据库或服务端队列处理较慢。time_total明显高于time_starttransfer:响应内容传输、带宽、丢包或客户端接收速度可能是主要因素。http_code变为 4xx、5xx 或请求超时:先处理错误和连接问题,不要只追求降低延迟。
单次请求不能作为结论。应在相同 URL、相同请求方式和相近业务负载下连续测试,并保留变更前后的结果。
2. 同时采集主机基础指标
以下命令主要用于读取状态,不会修改配置:
date
uptime
nproc
free -h
vmstat 1 5
df -h
df -i
ss -s
ip -br link
如果系统安装了 sysstat,再执行:
iostat -xz 1 5
sar -n DEV 1 5
若命令不存在,不要为了排查临时安装一批监控软件并改变生产环境。可以先使用已有监控、云平台指标或系统自带的 /proc、ss、ip 命令完成初步判断。
按指标区分瓶颈来源
CPU:看利用率、运行队列和等待类型
使用 vmstat 时,重点关注:
us:用户态 CPU,持续升高通常与应用计算、序列化、压缩、模板渲染或加密处理有关。sy:内核态 CPU,持续升高可能与网络包处理、系统调用、文件操作或连接数量有关。wa:I/O 等待,较高时不能简单判断为 CPU 不足,应转向检查磁盘和内存。st:虚拟化环境中的被窃取时间,升高表示虚拟 CPU 获得的运行时间受到影响,需要结合主机或服务商监控判断。r:可运行任务队列。应结合逻辑 CPU 数量nproc判断,若运行队列长期明显高于可用 CPU,才更接近 CPU 排队问题。
进一步查看占用 CPU 较高的进程:
ps -eo pid,ppid,comm,%cpu,%mem,etime --sort=-%cpu | head -n 15
判断方式如下:
- 某个应用进程的 CPU 持续偏高,且
us同步升高:优先检查该接口的计算逻辑、循环、序列化、压缩或并发配置。 - 多个工作进程同时接近满载,运行队列也升高:可能是整体并发超过当前 CPU 处理能力。
sy较高但应用 CPU 不突出:检查连接数、日志写入、文件操作和网络包处理。wa较高:不要继续增加应用工作进程,先检查磁盘和内存。st较高:应用层优化可能无法消除问题,应保留指标并核对服务器运行环境。
调整应用工作进程或线程数时,一次只改一个参数,并记录原值。增加并发可能提高吞吐,也可能让 CPU、内存、数据库连接池同时排队。验证时要同时查看响应时间、错误率和数据库连接数,而不是只看 CPU 是否下降。
内存:区分正常缓存和真正的内存压力
先查看内存概况:
free -h
vmstat 1 10
ps -eo pid,ppid,comm,%mem,rss,vsz,etime --sort=-%mem | head -n 15
Linux 使用空闲内存作为文件缓存并不等于内存不足,应重点关注:
available是否持续下降。vmstat中si、so是否持续出现,代表交换空间读入和写出。- 应用进程的常驻内存
RSS是否不断增长。 - 是否出现 OOM 终止记录。
- 内存紧张是否与 API 延迟、连接超时同时发生。
可以检查本次启动以来的内核记录:
sudo journalctl -k -b --no-pager | grep -Ei 'oom|out of memory|killed process'
如果 available 较低、交换读写活跃、应用延迟同步升高,优先检查应用缓存上限、连接池大小、响应缓冲区和内存泄漏。不要仅因为 free 数值较小就立即清理缓存或重启服务;清理缓存会改变后续访问行为,重启还可能造成连接中断。
如果只有单个进程内存持续增长,应先保存进程、应用日志和请求样本,再按应用自身的配置方式限制缓存或修复泄漏。若多个服务共同出现内存压力,则要重新核对整机上的进程、后台任务和数据库占用。
磁盘:用等待时间和利用率确认 I/O 瓶颈
执行:
df -h
df -i
iostat -xz 1 5
重点观察以下组合,而不是只看磁盘容量:
- 文件系统空间或 inode 接近耗尽:日志、上传文件、临时文件或缓存可能无法继续写入。
await持续升高且%util接近设备忙碌状态:磁盘请求正在排队。- CPU 的
wa与磁盘等待同时升高:网站静态文件、日志、数据库或应用临时文件可能是瓶颈。 - 磁盘指标正常但接口仍慢:不要把问题归因于磁盘,应继续检查应用和数据库。
检查大目录时,先确定目标路径,再执行只读统计:
sudo du -xhd1 /var 2>/dev/null | sort -h
日志处理、缓存清理和临时文件删除都可能影响生产服务。执行前应确认文件用途、保留期限和恢复方式。不要直接删除正在写入的日志或数据库文件;优先使用应用或日志系统支持的轮转机制,并在变更前保留配置备份。
网络:区分带宽不足、丢包和服务端排队
先确认网卡名称:
ip -br link
再查看实际接口的收发统计,将 eth0 替换为真实接口名:
ip -s link show dev eth0
ss -s
需要关注:
- 接口的
RX、TX丢弃和错误计数是否在测试期间持续增长。 - 连接总数、TCP 等待状态是否异常增加。
- 流量是否接近当前网络能力上限。
- 外部测试中的
time_connect、time_starttransfer和time_total哪一段增加。 - 是否只有特定接口或特定请求体变慢。
如果网卡错误或丢弃计数增长,应保存接口统计和发生时间,再核对服务器网络监控。不要未经确认直接修改 MTU、队列长度或内核网络参数,这些变化可能影响已有连接,且未必能解决链路问题。
如果连接时间正常、首字节时间很高,通常不是带宽不足,而是服务端接收后等待应用处理。相反,首字节时间正常但总时间明显增加,更应检查响应大小、出口流量、丢包和重传。
应用和数据库:系统指标正常时重点看请求内部
当 CPU、内存、磁盘和网络接口都没有明显异常,但 API 仍然变慢,应检查:
- 应用线程、协程或任务队列的等待时间。
- 数据库连接池是否耗尽,是否有连接获取等待。
- 慢查询、锁等待、事务持续时间和返回数据量。
- 外部依赖调用是否超时。
- Nginx 与应用之间的连接是否复用,应用是否能及时读取请求。
- 同一时间段内是否出现 5xx、超时或进程重启。
数据库不一定会把 CPU 跑满才造成接口变慢。连接池等待、锁等待和单条慢查询都可能使应用线程阻塞,而主机整体 CPU 仍然不高。因此,数据库指标应与应用请求日志按时间戳对齐,不能只看整机资源图。
变更准备:先留下可恢复的基线
保存服务配置和现状数据
确认 Nginx 实际配置位置和生效内容:
command -v nginx
nginx -V 2>&1
sudo nginx -T > "$HOME/nginx.before.$(date +%F-%H%M%S).txt"
如果实际配置目录确实是 /etc/nginx,可在确认磁盘空间和权限后备份:
sudo cp -a /etc/nginx "/etc/nginx.backup.$(date +%F-%H%M%S)"
应用配置应通过实际服务单元确认,不要猜测服务名:
systemctl list-units --type=service --state=running
systemctl cat <实际服务名>
尖括号中的内容需要替换为真实服务名。备份应用配置时,应保留原有属主、权限和软链接关系,并记录备份目录位置。
明确本次只改一个变量
建议把变更拆开:
- 先增加请求阶段日志,验证慢在哪一段。
- 再针对确认的瓶颈修改一个应用参数或配置项。
- 完成一轮观察后,才考虑下一项调整。
- 不要同时修改 Nginx、应用并发、数据库连接池和系统网络参数。
这样即使性能变化,也能知道是哪个改动产生了影响。
分步实施:从低风险测量到针对性调整
第一步:为 Nginx 记录请求耗时
如果 Nginx 是前端入口,可以增加请求总耗时和上游耗时。先用 nginx -T 找到实际的 http {} 和 server {} 配置位置,并选择一个未使用的日志格式名称。
在 http {} 中增加:
log_format perf_timing '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'request_time=$request_time '
'upstream_connect_time=$upstream_connect_time '
'upstream_response_time=$upstream_response_time '
'http_referer="$http_referer" '
'http_user_agent="$http_user_agent"';
在对应的 server {} 中启用:
access_log /var/log/nginx/access.log perf_timing;
日志路径应以现有配置和系统权限为准。如果原配置已有 access_log,不要直接覆盖原有日志策略,应先复制备份并确认磁盘空间。
修改后先检查语法,再平滑加载:
sudo nginx -t
sudo systemctl reload nginx
如果检查失败,不要执行重载,先根据报错恢复配置。若重载后发现日志异常或服务行为改变,使用变更前备份恢复,重新执行 nginx -t,确认通过后再加载。重载通常不等同于停止服务,但仍应在业务影响可控的时间操作。
日志中的判断方法:
upstream_connect_time高:Nginx 连接应用服务较慢,检查监听、连接队列和应用进程。upstream_response_time高:应用或数据库处理慢。request_time高而上游时间不高:可能是响应传输、客户端接收或网络问题。- 静态文件没有上游耗时,但总请求时间仍高:重点看磁盘读取、网络发送和连接状态。
第二步:根据证据处理 CPU 或应用并发
确认某个应用进程或接口是 CPU 瓶颈后,再查看该进程对应的服务日志和接口类型:
ps -eo pid,ppid,comm,%cpu,%mem,etime,args --sort=-%cpu | head -n 20
适合优先检查的内容包括:
- 是否有单个接口执行大量计算或返回过大的 JSON。
- 是否存在重复查询、循环调用或不必要的数据转换。
- 是否开启了高开销的压缩、加密或图像处理。
- 工作进程数量是否超过 CPU 和数据库连接池的承载能力。
- 是否有后台任务与前台请求争抢 CPU。
如果确实需要调整工作进程或线程数,应记录原值,修改后先做语法检查或配置校验,再平滑重载。验证时同时观察 CPU、r、API 错误率、数据库连接数和首字节时间。若 CPU 降低但延迟和错误率上升,说明并发调整方向不合适,应恢复原值。
第三步:处理内存压力,而不是盲目增加并发
确认内存压力后,优先限制无边界缓存、检查进程增长和减少不必要的并发。应用、运行时和数据库的内存配置必须结合实际版本与部署方式确认,不能直接套用其他环境的数值。
如果变更涉及服务重启,应提前确认:
- 是否允许已有连接断开。
- 是否有多个实例可以承接请求。
- 是否保存了当前配置和日志。
- 是否能通过原配置恢复启动。
如果没有可用的平滑重启或替代实例,不应在业务高峰直接重启。内存问题尚未定位时,单纯增加交换空间也不能替代应用内存治理;交换活动持续存在时,访问延迟可能进一步抖动。
第四步:处理磁盘和日志写入问题
当 iostat、vmstat 和应用日志同时指向磁盘等待时,先确认是哪类 I/O:
- 数据库文件读写。
- Nginx 或应用日志写入。
- 静态文件读取。
- 临时文件和上传文件。
- 日志轮转或后台备份任务。
只调整与问题直接相关的配置。例如日志量过大时,应使用现有日志轮转机制并确认保留策略;数据库慢时,应从慢查询、索引和锁等待入手,而不是直接删除数据文件或清空日志。
任何删除、覆盖或权限变更操作,都必须先备份、确认影响路径,并准备按原属主和权限恢复。数据库文件、运行目录和正在写入的日志文件不应作为普通临时文件处理。
第五步:处理网络异常或连接堆积
如果接口连接数持续增加、连接时间变长或网卡丢弃计数增长,可按以下顺序检查:
- 确认服务是否仍在正确监听目标地址和端口。
- 检查 Nginx 与应用的连接数、等待状态和错误日志。
- 对照网卡收发、丢弃和错误计数。
- 对照外部
curl分段时间,确认是建连慢、首字节慢还是传输慢。 - 核对服务器侧网络监控和业务高峰流量。
不要只用 ping 判断 HTTP 或 API 是否正常,也不要因为带宽使用率较低就排除丢包、连接排队和服务端处理延迟。网络调整应在已确认问题属于网络层时进行,并保留原配置和恢复命令。
验证观察:用同一组指标确认改动有效
每次变更后,使用与变更前相同的 URL、请求方法、测试数据和测试位置重新测量:
URL='https://example.com/health'
for i in 1 2 3 4 5; do
curl -sS -o /dev/null \
-w "starttransfer=%{time_starttransfer}s total=%{time_total}s code=%{http_code}\n" \
"$URL"
done
uptime
free -h
vmstat 1 5
ss -s
成功验证至少应同时满足:
- 首字节时间或总响应时间相对变更前基线改善。
- HTTP 状态码、超时率和连接失败率没有恶化。
- CPU 运行队列、内存交换、磁盘等待或网络错误没有转移性升高。
- 应用日志中的队列等待、数据库连接池等待和慢查询没有增加。
- Nginx 的
request_time与上游耗时变化符合预期。 - 网站、API 或长连接业务的实际错误表现得到改善,而不是只改善了某一个测试请求。
观察时间应覆盖至少一个完整的业务高峰,或覆盖能够稳定复现问题的流量周期。低流量时暂时变快,并不代表生产环境已经恢复。
失败处理与回滚边界
出现以下情况时,应停止继续叠加变更,并优先恢复上一版本配置:
nginx -t检查失败。- 变更后出现 5xx、连接拒绝、请求超时或服务无法正常加载。
- CPU、内存、磁盘或网络指标比变更前更差。
- API 平均延迟下降,但高分位延迟、错误率或数据库等待上升。
- 日志没有记录到预期字段,导致无法判断实际效果。
- 业务高峰到来后出现新的排队、断连或进程重启。
Nginx 配置回滚时,使用此前确认过的备份恢复,不要凭记忆手工重写整份配置。恢复后仍需执行语法检查,再进行平滑加载:
sudo nginx -t
sudo systemctl reload nginx
应用配置回滚也应恢复原文件、属主和权限,并按照该应用支持的平滑重载或受控重启方式执行。若无法确认恢复后的配置是否完整,应先保留现场、保存日志和当前指标,再暂停进一步操作。
对于“指标正常但用户仍慢”的情况,不要反复调整 CPU、内存或网络参数。此时应回到请求分段结果,继续核对应用队列、数据库锁等待、连接池和外部依赖。对于“系统指标异常但接口测试正常”的情况,则要检查采集时间、测试流量和是否存在后台任务,避免把无关任务误认为网站或 API 瓶颈。
最终应保留变更前后两组数据、实际修改项、验证时间和回滚触发条件。只有当相同业务场景下延迟、错误率和资源指标都稳定改善,并完成观察窗口,才适合保留本次变更。