https://www.live400.com/newsdetail/id/70.html CPU 只有 30%,系统却慢到不可用?-江苏立维-专注监控、运维服务(Zabbix|Prometheus|APM|日志|数据库)
  首页     >     新闻动态     >     CPU 只有 30%,系统却慢到不可用?

CPU 只有 30%,系统却慢到不可用?

发布日期:2026-02-11    阅读数:12


这是我们排查最多的

“假健康事故”




这是一次非常典型的事故场景。

业务反馈系统响应明显变慢,
用户投诉集中在「接口卡顿」「页面转圈」。

首先打开系统监控进行排查:

CPU Usage:      30%Memory Usage:   55%Load Average:   0.8Disk IO:        正常

Grafana指标全都正常。

从资源视角看,系统甚至谈不上有压力

但事实是——
请求已经慢到用户无法接受。






CPU不高≠系统在“正常工作”




这是很多团队在监控体系上踩的第一个认知坑。

CPU 只代表一件事:

CPU 正在消耗多少计算资源

完全不能反映

  • 请求是否被阻塞

  • 线程是否在等待

  • I/O 是否成为瓶颈

  • 业务链路是否已经“局部瘫痪”

一句话总结:

CPU 低,只能说明系统没在算,不代表系统没在等。



CPU 低系统慢,原因何在?






1️⃣线程池被 I/O 阻塞“悄悄吃满”

我们先看一段最常见的 Java 服务结构:

@RestControllerpublic Result queryOrder() {    Order order = orderService.getOrder(id);    return Result.ok(order);}

在代码层面,它看起来是同步、顺序、可控的。

但在运行时,真实路径可能是:

HTTP Request  ↓Tomcat Worker Thread  ↓数据库连接池获取连接(阻塞)  ↓执行 SQL(慢查询)  ↓等待下游 RPC 返回

如果其中任意一步变慢:

  • Tomcat 工作线程被占用

  • 新请求开始排队

  • 响应时间指数级上升

而 CPU 使用率呢?

几乎不变。

因为线程大多数时间都在 

WAITING / TIMED_WAITING

2️⃣连接池耗尽,比 CPU 打满更致命

我们在事故中经常看到这样的监控组合:

DB CPU:           40%DB QPS:           正常Application TPS:  下降

问题在哪?

HikariCP Active Connections: 50 / 50Waiting Threads:             持续增长

这意味着:

  • 数据库还能扛

  • 但应用已经拿不到连接

  • 请求在 getConnection()阶段就被阻塞

从 JVM 角度看:

HTTP-8080-exec-123" waiting on condition

系统没有崩溃,

已经无法提供有效服务

3️⃣一个慢接口,拖垮整个系统吞吐

很多团队忽略了一个事实:

系统吞吐 ≈ 最慢路径的能力

假设你的接口响应时间从 50ms 变成 300ms:

原 QPS ≈ 1000实际 QPS ≈ 160

CPU 依然很低,
但线程池开始排队,延迟开始堆积。

这类问题的典型特征是:

  • CPU 不高

  • 内存不满

  • 但 P95 / P99 延迟持续升高

如果你只盯着平均值和 CPU,是完全感知不到的



Java 应用怎么查?




当你确认:

  • CPU 不高

  • 内存正常

  • 但请求明显变慢

第一件事,别再盯 Grafana 了。

你需要直接进入 JVM 内部,看它到底在“忙什么”。

1️⃣ 先看线程:CPU 不高,线程在干嘛?

第一步,永远是线程状态。

jstack <pid> > jstack.log

重点不是线程数量,而是状态分布

RUNNABLEBLOCKEDWAITINGTIMED_WAITING

在“CPU 低但系统慢”的事故中,我们最常看到的是:

  • RUNNABLE 很少

  • WAITING / TIMED_WAITING 占大多数

典型线程栈长这样:

"HTTP-8080-exec-124" prio=5 tid=0x00007f8c940 waiting    at java.util.concurrent.locks.LockSupport.park()    at java.util.concurrent.FutureTask.get()

这说明什么?

线程没有在算,而是在等结果。

等什么?

  • 数据库返回

  • 下游 RPC

  • 锁释放

  • 线程池资源

2️⃣ 看线程池:不是没线程,是用不上线程

很多团队只关心线程池大小,却不看运行状态

如果你用的是 ThreadPoolExecutor,重点看这几个指标:

activeCount queueSize completedTaskCount

一个非常危险的组合是:

activeCount ≈ maxPoolSizequeueSize 持续增长

这意味着:

  • 线程已经被慢任务占满

  • 新请求只能排队

  • 延迟开始指数级放大

而 CPU?

依然不高。

3️⃣ 再看 GC:不是 Full GC,但“轻微抖动”很要命

很多人一看到系统慢,就下意识否定 GC:

“没有 Full GC,应该不是 GC 问题。”

但真实情况是:

  • 频繁 Young GC

  • Stop The World 很短,但次数极多

你会在 GC 日志里看到类似:

[GC (Allocation Failure) 256M->128M(512M), 15ms]

15ms 不长,但如果:

每秒 20 次

那对延迟型服务来说,就是灾难。

尤其是:

  • 接口本身就慢

  • 请求已经在排队

GC 抖动会直接放大用户感知延迟。

4️⃣ 堆没满,但对象“活得太久”

这是非常容易被忽略的一点。

jmap -histo <pid> | head -20

你可能会看到:

num     #instances    #bytes  class name --------------------------------------- 1:      8,000,000     640MB   byte[] 2:      2,300,000     184MB   java.lang.String

这说明:

  • 对象在堆里大量堆积

  • GC 清不掉

  • 线程在分配内存时越来越慢

CPU 不高,
但 JVM 已经开始效率衰减

5️⃣ 最后看一个致命点:同步与锁

如果线程栈里频繁出现:

java.lang.Object.wait() java.util.concurrent.locks.AbstractQueuedSynchronizer

那你基本可以确认:

系统慢,不是因为算得慢,而是锁抢不过来。

这类问题的特点是:

  • CPU 利用率低

  • 吞吐下降明显

  • 延迟突然拉长

而且,扩容几乎无效




Prometheus + Grafana 

为啥看不出问题?




因为大多数监控只做了资源观测,没有做系统行为观测

常见指标是:

node_cpu_seconds_total node_memory_MemAvailable_bytes

但真正该关注的,是这些:

http_server_requests_seconds_bucket jvm_threads_state{state="BLOCKED"hikaricp_connections_active mysql_global_status_threads_running

如果你没有:

  • 接口分位延迟(P95 / P99)

  • 线程池状态

  • 连接池使用情况

  • 关键依赖的响应时间

那么监控只能告诉你一句话:

“服务器还活着。”

但业务是否健康,它不知道。




中小团队常忽视的“慢性事故”




我们复盘过大量事故后发现:

这类问题很少第一时间报警

通常是用户先感知

再由人肉排查发现

原因只有一个:

监控体系没有覆盖“用户体验劣化”的早期信号

等到 CPU 真正升高时,
系统往往已经处在雪崩边缘。




一个更靠谱的判断逻辑




与其问:

“CPU 高不高?”

不如问这三个问题:

  1. 请求在系统中卡在哪一层?

  2. 哪个资源正在成为隐形瓶颈?

  3. 如果现在继续变慢,谁能第一时间发现?

真正成熟的运维体系,
不是等系统挂了再报警,
而是能在**“慢”刚开始出现时就介入**。



写在最后




CPU 只有 30%,系统却慢到不可用,
从来不是一个偶发问题。

它往往意味着:

  • 系统已经进入亚健康状态

  • 只是还没触发致命阈值

真正的分水岭,不在于是否出过事故,而在于:

系统开始变慢的那一刻,
你能不能看见?

所以、单纯的监控系统层面的cpu、内存、磁盘等等,

是远远不够的。

线程在等什么?

连接池还有多少空闲?

GC 暂停是否隐形拖垮了延迟?

数据库/Redis 调用是否在异常?

只有把以下这些 JVM 核心亚健康指标 

实时采集、可视化、设置阈值告警,

你才能在“页面刚开始卡”而不是“系统彻底挂”的时候发现问题。

新闻搜索

相关新闻

云安全风险发现,从现在开始
返回顶部-立维
公众号
关注微信公众号
电话咨询
服务热线:400-006-8618
项目咨询
项目合作,欢迎发邮件咨询
liveserver@live400.com