3. 单机系统的瓶颈:CPU、内存、磁盘IO与网络IO,压测与性能分析工具

好,咱们进入第三章。这一章我打算聊聊单机系统的瓶颈。

你想想看,很多刚入行的朋友,一上来就想着怎么搞分布式、怎么上微服务。但说实话,大部分系统在单机阶段的问题都没解决利索。我见过太多项目,业务逻辑还没跑通呢,就开始拆服务,结果拆完发现性能更差了。

所以,咱们先把单机吃透。单机搞明白了,分布式才有根基。

3.1 CPU瓶颈:你的计算核心够用吗?

CPU是系统的“大脑”。它出问题,整个系统就卡住了。

我个人习惯,看CPU是否瓶颈,先看两个指标:使用率负载

  • 使用率:CPU在干活的时间占比。超过80%就要警惕了。
  • 负载:等待CPU处理的任务队列长度。负载超过CPU核心数的2倍,基本就堵车了。

我在项目中遇到过一个问题:一台8核的服务器,CPU使用率只有30%,但系统响应特别慢。为什么?后来发现是上下文切换太频繁了。线程数开得太多,CPU大部分时间都在切换线程,而不是真正干活。

核心观点:CPU瓶颈不一定是算力不够,也可能是调度不合理。

排查CPU问题,我常用topperf。比如:

# 查看CPU使用率和负载
top -bn1 | head -5

# 查看每个CPU核心的使用情况
mpstat -P ALL 1

# 分析热点函数(这个很关键)
perf top

小技巧:用perf top能看到哪个函数在吃CPU。我曾经发现一个加密算法占用了40%的CPU,换成硬件加速后,性能直接翻倍。

3.2 内存瓶颈:数据放不下,速度跟不上

内存是系统的“工作台”。工作台太小,东西放不下,就得频繁去磁盘搬东西——那就慢了。

内存瓶颈通常有两种表现:

  1. 内存不足:系统开始使用Swap,性能断崖式下跌。
  2. 内存带宽:数据量太大,内存读写速度跟不上CPU。

我记得有一次做量化交易的回测系统,数据量大概有50GB。服务器内存只有64GB,按理说够用。但回测跑起来后,发现磁盘一直在狂转。查了半天,原来是内存碎片化严重,导致大块连续内存分配失败,程序被迫使用文件映射。

避坑指南:我曾经因为没注意内存碎片,导致一个高频交易程序在运行8小时后突然崩溃。后来改用内存池,问题才解决。

内存分析工具:

# 查看内存使用情况
free -h

# 查看进程内存映射
pmap -x <pid>

# 内存泄漏检测(这个我经常用)
valgrind --leak-check=full ./your_program

3.3 磁盘IO瓶颈:慢,是真的慢

磁盘IO是单机系统里最容易被忽视的瓶颈。你想想看,CPU处理一个指令是纳秒级,内存访问是微秒级,而磁盘IO是毫秒级——差了三个数量级。

磁盘瓶颈的典型症状:

  • iowait高:CPU在等磁盘干活。
  • IOPS打满:每秒读写次数达到上限。
  • 吞吐量不足:带宽不够,大文件读写慢。

我做过一个日志系统,每秒要写几万条日志。刚开始用机械硬盘,结果iowait直接飙到90%。后来换成SSD,问题解决了。但更关键的是,我改了日志的写入策略——从每条日志都刷盘,改成批量写入。

经验之谈:磁盘IO的优化,很多时候不是换硬件,而是改策略。

磁盘IO排查工具:

# 查看磁盘IO情况
iostat -x 1

# 查看进程IO
iotop

# 文件系统缓存分析
cat /proc/meminfo | grep -E "Dirty|Writeback"

3.4 网络IO瓶颈:看不见的“堵点”

网络IO在单机阶段可能不明显,但一旦涉及跨机通信,它就是最大的瓶颈。

网络瓶颈的几个关键指标:

指标 说明 警戒线
带宽 每秒能传输的数据量 超过80%就要注意
延迟 数据包往返时间 超过10ms算高延迟
丢包率 数据包丢失比例 超过0.1%就有问题
连接数 同时建立的TCP连接数 超过65535可能出问题

我记得有一次做行情推送系统,数据量不大,但延迟就是降不下来。查了半天,发现是TCP Nagle算法在作祟。小包被延迟发送,导致行情数据不能实时到达。关闭Nagle后,延迟从50ms降到了2ms。

避坑指南:我曾经在金融交易系统中,因为没设置TCP_NODELAY,导致订单确认延迟高了30ms。在交易系统里,30ms意味着什么?可能是一笔交易的盈亏。

网络排查工具:

# 查看网络连接状态
netstat -ant | grep TIME_WAIT | wc -l

# 抓包分析(这个最直观)
tcpdump -i eth0 port 8080 -w capture.pcap

# 延迟测试
ping -c 10 target_ip

3.5 压测与性能分析工具:用数据说话

说了这么多瓶颈,怎么找到它们?靠猜是不行的。得用工具,用数据说话。

我常用的压测工具:

  • wrk:HTTP压测,轻量级,适合Web服务。
  • ab:Apache Bench,简单粗暴。
  • sysbench:数据库和系统压测,功能全面。
  • stress:模拟CPU、内存、IO压力。

性能分析工具:

  • perf:Linux性能分析利器,能定位到函数级别。
  • flamegraph:火焰图,可视化CPU热点。
  • strace:跟踪系统调用,看程序在干什么。
  • gprof:GNU性能分析工具。

举个例子,用wrk压测一个HTTP服务:

# 压测:100个连接,持续30秒
wrk -t12 -c100 -d30s http://localhost:8080/api

# 输出示例
Running 30s test @ http://localhost:8080/api
  12 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    45.67ms   12.34ms 123.45ms   75.00%
    Req/Sec     2.34k   345.67     3.45k    70.00%
  70123 requests in 30.00s, 89.56MB read
Requests/sec:   2337.43
Transfer/sec:      2.99MB

看到这个结果,如果延迟平均45ms,但最大延迟123ms,说明有抖动。这时候就要用perf或者火焰图去查,到底是哪个函数在拖后腿。

我的习惯:压测不是跑一次就完事。我会逐步增加并发,观察各项指标的变化曲线。当某个指标突然拐弯时,那就是瓶颈所在。

3.6 一张图看懂单机瓶颈

下面这张图,是我自己总结的单机系统瓶颈分析框架。你可以把它当成一个检查清单。

单机系统瓶颈分析框架 单机系统 CPU瓶颈 内存瓶颈 磁盘IO瓶颈 网络IO瓶颈 使用率过高 负载过高 上下文切换 内存不足 内存碎片 带宽不足 iowait高 IOPS打满 吞吐量不足 带宽瓶颈 延迟过高 丢包/连接数 压测工具:wrk / ab / sysbench / stress 分析工具:perf / flamegraph / strace / gprof

这张图把单机瓶颈分成了四大类。每个大类下面,又有具体的表现。你遇到性能问题时,可以对照这张图,先定位是哪个大类,再往下深挖。

我的建议:把这图打印出来贴在工位上。每次排查性能问题,先看它,能省不少时间。

好了,单机瓶颈就聊到这儿。记住一句话:没有万能工具,只有对症下药。CPU、内存、磁盘、网络,每个瓶颈的解法都不一样。但前提是,你得先找到它。


公众号:蓝海资料掘金营,微信deep3321