压测 TPS 卡在 800CPU 只跑四成六步定位法

TPS 卡在 800 不是 CPU 的锅:Hikari 连接池只给了 50 个连接、超时还没配,几百个请求全堵在 getConnection()。改完 1600。

先看那条骗人的 CPU 曲线

场景没什么稀奇:核心接口单压,并发从 100 加到 200,TPS 涨到 800 就躺平。再加到 300,不涨反跌。

看监控,CPU 只跑到四成。第一反应自然是"机器还没吃满,加并发就完事了"。把线程数翻倍,TPS 掉到 700 出头。

CPU 不满,说明瓶颈根本不在计算层。计算层长什么样?CPU 打满、GC 频繁、上下文切换爆炸。CPU 闲着的卡顿,八成是在等------等锁、等连接、等 IO、等下游。

记住一句话:别盯计算层,分层往下摸。应用层、中间件层、数据库层,一层一层排。

六步,一步都别省

排查流程固定成六步,少讲一步面试官就当你没做过:

flowchart TD A[现象] -->|定位起点| B[工具] B -->|采集证据| C[分析] C -->|锁定层| D[根因] D -->|给出改法| E[方案] E -->|复测对比| F[数据] F -->|没解决| B

顺序不能乱。现象是"TPS 卡 800、CPU 四成";工具拿来看证据;分析把证据收敛到某一层;根因是那一层里具体哪行配置;方案得可执行;数据是改完的对比。

面试里最容易漏掉的是最后一步,数据。说"我改了连接池"没说服力,说"TPS 从 800 到 1600"才叫做过。

为什么第一把工具是 netstat 而不是 jstack

先用 netstat(或 ss)看连接状态分布:

bash 复制代码
netstat -n -p tcp | awk '{print $$6}' | sort | uniq -c | sort -rn

输出大概长这样:

text 复制代码
   812 TIME_WAIT
   634 ESTABLISHED
   287 CLOSE_WAIT

满屏 TIME_WAIT,大量连接挤在同一条道上排队。方向当场锁死:问题在连接层,不在计算层。

这里有个容易搞混的点。TIME_WAIT 多,说明连接反复建立销毁、没有复用;CLOSE_WAIT 多,是应用侧没关连接,通常意味着连接泄漏。两者指向的原因完全不同,别混着说。

根因:50 个连接接 200 个并发

顺着连接层往下,查数据库连接池配置:

yaml 复制代码
hikari:
  maximum-pool-size: 50
  connection-timeout: 0   # 没配超时

最大连接数只给 50,超时也没配。并发爬到 200 以上,几百个请求全在池子外面排队等连接。每个请求平均等几十上百毫秒,TPS 上不去,CPU 在旁边闲着看戏。

这就是典型的"CPU 不满但吞吐上不去":线程全阻塞在 getConnection(),一点计算量都没有。

改法很直接:

yaml 复制代码
spring:
  datasource:
    hikari:
      maximum-pool-size: 200
      minimum-idle: 50
      connection-timeout: 3000
      idle-timeout: 600000
      max-lifetime: 1800000

connection-timeout 必须明确给值。给了超时,池子撑不住时会快速失败返回,而不是把请求无限挂在那儿------快速失败比慢慢等死好排查得多。

复测:800 → 1600

同一个脚本、同一台机器、同样并发 200,重压一次:

指标 修复前 修复后
TPS 800 1600
P99 响应时间 480ms 210ms
CPU 使用率 40% 68%
连接池等待 大量排队 基本为零

TPS 翻倍,CPU 从四成涨到接近七成。这时候 CPU 涨上来是好事,说明请求终于被真正处理,而不是堵在池子门口。

面试官想听的就是这组前后对比数字。

两个高频变体

变体一:响应时间从 200ms 飙到 800ms,TPS 却正常。

还是那套分层思路,但先上链路追踪,别急着改代码。查出来是一条慢 SQL 在 500 万行的表上做全表扫描,加个联合索引,响应时间降到 80ms 以内。

迷惑点在于 TPS 没掉。TPS 正常说明吞吐没受影响,慢的是单请求耗时,方向该往"单条查询效率"走,跟连接、并发没关系。

变体二:CPU 跑满 100%,接口超时。

top -Hp <pid> 找出吃 CPU 最高的线程 ID,转十六进制,再 jstack <pid> | grep -A 30 <hex> 定位栈帧。常见结果是一段复杂正则或弹性回缩逻辑在高并发下被反复打爆。优化那段正则,CPU 降到 30% 以下。

top + jstack 是 CPU 打满场景的核心工具链,配上线程 ID 转十六进制,基本能追到具体代码行。

三句话版本

现象定起点,工具取证,分析锁层,根因落到具体配置或代码,方案可执行,数据做对比。

面试回答六步一步别省。最值钱的永远是最后那步------用前后对比数据把"我真的做过"砸出来。

写在最后

压测调优拼的不是工具多,是分层排查的习惯。CPU 不满的时候,你第一反应是加机器还是查连接池?这两个方向之间往往差着整整一倍 TPS。

顺手的赞,点一下就行。

相关推荐
skywalk816316 分钟前
登到192.168.1.5那台机器,看看今天白天,大约从早晨到晚上,都卡住了。看看因为什么卡住,为什么卡住而没有杀死那个导致卡死的进程,为什么
运维·系统·freebsd
运维行者_22 分钟前
网络监控工具怎么选?从设备监控到智能运维的能力清单
运维·服务器·开发语言·网络·人工智能·支持向量机·php
晚风吹北巷2 小时前
Linux复习篇(自用)
linux·运维·服务器·1024程序员节
风哥2号2 小时前
数据库教程FGMT69:PostgreSQL运维诊断与监控分析
运维·数据库·postgresql
彭亚川Allen2 小时前
从零手搓 RAG 之 Embedding 技术
前端·后端·面试
Sailing3 小时前
🚀🚀【封闭结束4】Agent 工具调用工程化:把 Tool Runtime 做扎实
人工智能·面试·agent
Harrison Ben3 小时前
(原创)SAP FI自动入账奥义:FBKP FBKA FBKF
运维·sap·sap fico·sap运维·sap 实施
无足鸟ICT3 小时前
【RHCA+】reboot命令(重启)
linux·运维·服务器·1024程序员节
见叶之秋4 小时前
【C++】红与黑的边界:红黑树从插入到自检
数据结构·c++·算法·面试
考研保研资料分享4 小时前
2023历史学跨保山大马理论:两轮笔面试、课程论文与方向取舍
面试·职场和发展