本质是流量切过去但未切匀,需逐台查cpu核心/线程分布、qps/响应时间/gc等指标,排查clb/nginx/ingress粘滞、网卡中断扎堆、numa跨节点访问、jvm绑核缺失及代码隐性热点。

流量切换后CPU负载分布不均,本质不是“流量没切过去”,而是“流量切过去了,但没切匀”。关键要跳出“看总QPS是否上涨”这种粗粒度判断,直接定位到请求在节点/核心/线程层面的落点偏差。
先确认是不是真不均:别被平均值骗了
监控上显示“整体CPU 30%”,不代表每台机器都30%。必须逐台查:
- 用 mpstat -P ALL 1 看各CPU核心使用率,是否存在单核长期95%+而其他核空闲(网卡中断扎堆)
- 用 top -H -p
看Java进程内线程分布,是否大量请求线程挤在少数几个核上运行 - 对比各实例的 QPS、平均响应时间、线程数、GC频率 四个指标,三台机器QPS相近但一台CPU翻倍,基本可排除流量量级问题,指向处理效率或资源争用
重点查流量路径中的“粘滞点”
流量切换常走CLB/Nginx/Ingress,而这些组件的调度策略极易导致“连接粘滞”:
- 检查CLB是否启用 WRR(加权轮询)或 least_conn —— 这两种算法只在建连时分配,后续长连接请求全打到同一Pod,形成热点
- 查Nginx配置里有没有 ip_hash 或 sticky 指令,尤其在HTTP/1.1 Keep-Alive或HTTP/2场景下,一个客户端可能持续压垮单个后端
- 确认Ingress是否启用了 sessionAffinity: ClientIP,小范围IP段集中访问会直接放大倾斜
排查底层资源绑定与中断分布
即使应用层流量均匀,系统层也可能因硬件调度失衡导致CPU假高:
- 执行 cat /proc/interrupts | grep eth,看网卡中断是否集中在1-2个CPU上;再用 ethtool -l eth0 确认是否开启多队列,队列数是否≥CPU核心数
- 用 numastat 查看各NUMA节点内存访问命中率,跨节点访问延迟高会拖慢处理速度,让某节点CPU看似忙实则低效
- 检查Java进程是否绑核 —— 若未用 numactl 或cgroup限制,JVM线程可能被内核随机调度到不同NUMA节点,引发缓存失效和内存等待
验证应用自身是否存在隐性热点
有些不均来自代码逻辑,和流量分发无关:
- 查数据库SQL执行计划,确认是否某台机器因缓存未预热,反复执行慢查询;或分库分表键设计不合理,导致某实例承担80%数据读写
- 检查定时任务是否在部分机器上重复触发(如未加分布式锁),或某台机器恰好承担了清理大表、导出报表等重IO任务
- 用 jstack 抓线程快照,看高CPU机器上是否有大量线程卡在 WAITING on java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject —— 锁竞争会导致CPU空转升高










