第2章:性能度量与监控——先学会看仪表盘,再谈修车

性能调优这件事,说白了就是「先找到问题,再解决问题」。但问题在哪?怎么找?靠猜肯定不行。你得有一套靠谱的仪表盘和度量标准。这一章,我们就聊聊怎么给系统装上「仪表盘」。

2.1 关键性能指标(KPI)——你得知道看什么

我刚开始做性能优化那会儿,经常犯一个错:看到系统慢,就盲目加机器、加缓存。结果呢?钱花了,问题还在。后来我明白了——你得先定义「什么是慢」。

性能KPI,就是用来量化「慢」的尺子。常用的有这么几把:

指标 英文 说明 我常用的阈值
响应时间 Response Time 从发请求到收到响应的时间 API < 200ms,页面 < 2s
吞吐量 Throughput 单位时间能处理多少请求 看业务,但必须关注峰值
并发数 Concurrency 同时处理的请求数量 别超过CPU核心数的2倍
错误率 Error Rate 请求失败的百分比 超过1%就要报警
资源利用率 Utilization CPU、内存、磁盘、网络的使用率 持续超过80%就要警惕

核心原则:不要只看平均值。P99(99%的请求都在这个时间内完成)比平均值更能反映真实体验。我在项目中遇到过,平均响应时间只有50ms,但P99高达5s——用户体验极差,平均值骗了所有人。

2.2 性能监控工具——你的「听诊器」

有了KPI,还得有工具去采集。Linux自带的命令行工具,就是最直接的「听诊器」。别小看它们,我到现在排查线上问题,第一反应还是敲这几个命令。

2.2.1 top / htop——看CPU和内存的「实时心电图」

top 是我用得最多的命令。每次登录服务器,第一件事就是敲 top,看看哪个进程在「吃」资源。

# 基本用法
top

# 按CPU使用率排序(默认就是)
top -o %CPU

# 按内存使用率排序
top -o %MEM

# 只查看某个用户的进程
top -u nginx

输出里,我最关注三列:%CPU、%MEM、RES(常驻内存)。如果某个进程CPU持续超过80%,基本可以断定它有问题。

htop 是 top 的增强版,支持鼠标操作、彩色显示、树形进程视图。我个人习惯装 htop,因为看起来更直观。但生产环境有时没装,所以 top 的基本功必须扎实。

小技巧:在 top 里按 1,可以查看每个CPU核心的使用情况。我曾经发现一个8核服务器,只有1个核心跑满,其他核心空闲——典型的单线程瓶颈。

2.2.2 vmstat——系统整体健康度「体检报告」

vmstat 能告诉你系统在「忙什么」。它把系统状态分成几块:进程、内存、交换分区、IO、CPU。

# 每2秒输出一次,共5次
vmstat 2 5

输出示例:

procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 2  0      0 1024000  50000 800000    0    0    10    20  100  200 30 10 60  0  0

我重点看这几列:

  • r(运行队列):如果持续大于CPU核心数,说明CPU不够用。
  • si / so(交换内存):如果非零,说明物理内存不足,系统在频繁换页——这是性能杀手。
  • wa(IO等待):如果超过30%,磁盘IO大概率是瓶颈。

避坑指南:我曾经遇到一个案例,wa 高达50%,但磁盘监控显示读写量不大。后来发现是内存不足导致大量换页,换页又引发磁盘IO。表面是磁盘问题,根因是内存。所以,看指标要联动分析,别孤立看一个。

2.2.3 iostat——磁盘IO的「显微镜」

当怀疑磁盘是瓶颈时,iostat 就是你的利器。

# 查看磁盘IO统计,每2秒一次
iostat -x 2

# 只看某个设备
iostat -x sda 2

关键指标:

  • %util:磁盘忙碌百分比。超过80%就要注意。
  • await:IO请求的平均等待时间(毫秒)。机械盘一般 < 10ms,SSD < 1ms。
  • svctm:IO请求的服务时间。如果远小于 await,说明请求在排队。

嗯,这里要注意:%util 100% 不一定代表磁盘坏了,也可能是请求太密集。我见过一个日志系统,%util 长期100%,但 await 只有2ms——说明磁盘本身很快,只是请求量太大。这时候加磁盘或优化写入策略才是正解。

2.2.4 netstat——网络连接的「交通摄像头」

网络问题往往隐蔽。netstat 能帮你看到谁在连你的服务器,连接状态如何。

# 查看所有TCP连接
netstat -ant

# 统计连接状态
netstat -ant | awk '{print $6}' | sort | uniq -c

# 查看监听端口
netstat -tlnp

我最关注 TIME_WAIT 和 CLOSE_WAIT:

  • TIME_WAIT 过多:通常是短连接太多,可以考虑连接池或调整内核参数。
  • CLOSE_WAIT 堆积:说明程序没正确关闭连接——这是代码bug,得改程序。

实战经验:有一次线上服务响应变慢,netstat 一看,CLOSE_WAIT 有3000多个。查代码发现是HTTP客户端没设置超时,连接用完没释放。修复后,响应时间从2s降到100ms。

2.3 性能基准测试——没有基线,就没有优化

你优化了系统,怎么知道有没有效果?靠感觉?不行。你得先跑一次基准测试,拿到「优化前的数据」,然后优化完再跑一次,对比差异。

基准测试的核心原则:控制变量。每次只改一个参数,其他条件不变。

2.3.1 常用基准测试工具

工具 用途 一句话总结
ab (Apache Bench) HTTP接口压测 简单快速,适合单接口
wrk HTTP接口压测 支持Lua脚本,更灵活
sysbench CPU/内存/磁盘/数据库 全能型,适合系统级测试
fio 磁盘IO性能 磁盘测试的「金标准」
iperf 网络带宽 测网络吞吐量

2.3.2 一个完整的基准测试流程

我一般按这个步骤来:

  1. 确定测试目标:比如「测一下Nginx的QPS上限」。
  2. 准备测试环境:尽量和生产环境一致。别在笔记本上测,然后说服务器能抗10万QPS——不现实。
  3. 预热:先跑几分钟,让系统进入稳定状态。你想想看,刚启动的JVM和运行半小时的JVM,性能差很多。
  4. 正式测试:记录响应时间、吞吐量、错误率、资源利用率。
  5. 分析结果:找到瓶颈点。
  6. 优化:改一个参数,重复步骤3-5。
# 用ab做简单压测
ab -n 10000 -c 100 http://localhost:8080/api/test

# 用wrk做更灵活的压测
wrk -t12 -c400 -d30s http://localhost:8080/api/test

我的习惯:每次压测结果都保存到文件,标注日期和改动内容。这样回头看,能清楚知道「改了啥,效果如何」。没有记录,优化就是瞎忙活。

2.4 本章知识体系

下面这张图,帮你把本章的核心逻辑串起来:

性能度量与监控知识体系 性能度量与监控知识体系 目标:找到性能瓶颈,量化优化效果 KPI 定义 监控工具 基准测试 关键指标 • 响应时间 (P50/P99) • 吞吐量 (QPS/TPS) • 并发数 / 错误率 • 资源利用率 命令行工具 • top / htop → CPU & 内存 • vmstat → 系统整体健康 • iostat → 磁盘IO • netstat → 网络连接 测试工具 • ab / wrk → HTTP压测 • sysbench → 系统级测试 • fio → 磁盘性能 • iperf → 网络带宽 输出:性能基线报告 + 瓶颈定位 核心思想:先度量,后优化。没有数据,一切优化都是「玄学」。

这张图想表达的核心就一句话:先定义KPI,再用工具采集数据,最后通过基准测试建立基线。三者缺一不可。

总结一下:性能调优不是上来就改代码、调参数。你得先学会「看」。看KPI、看监控、看基准数据。看得多了,你自然就知道问题在哪。我见过太多人,工具用得溜,但不知道看什么——那等于白搭。记住:度量是优化的前提,监控是度量的手段,基准是优化的标尺。