性能优化-案例二

案例二:大促高峰期全站接口响应卡顿(系统与配置层面)

 

【故障现象】

在大促活动高峰期,网站整体响应变得极其缓慢,不仅订单接口,连简单的商品列表接口也出现大量超时,且服务器 CPU 使用率并不高。

【全链路排查与指标定位】

1.Linux 操作系统层(排除资源饱和)
使用 top 和 iostat 命令观察服务器状态。
指标发现:CPU 使用率仅 40%,磁盘 I/O 的 %util 也不高,但系统的 Load Average(平均负载)却飙到了 50 以上。
结论:CPU 空闲但负载极高,说明有大量的线程处于 “不可中断睡眠(D状态)” 或 “等待(Waiting)” 状态,通常意味着应用在等待某些外部资源(如数据库连接、锁)。

2.Java 应用层(定位线程阻塞)
使用 jstack <pid> 导出 Java 进程的线程堆栈,或者通过 Arthas 的 thread -n 5 查看最忙/阻塞的线程。
指标发现:发现大量业务线程的状态为 WAITING (parking),且堆栈信息都卡在 DruidDataSource.getConnection(获取数据库连接)这一步。
关联排查:检查 JVM 的 GC 日志,发现 Full GC 频率并不高,排除了内存溢出导致的卡顿。

3.中间件与数据库层(定位连接池瓶颈)
结合 Java 应用的配置文件和 MySQL 的状态进行交叉验证。
指标发现:Java 应用的数据库连接池(如 HikariCP 或 Druid)配置的 maximum-pool-size 为 50,而当前并发请求量达到了 200。同时,通过 ss -s 或 netstat 发现应用服务器与 MySQL 之间的 ESTABLISHED 连接数死死卡在 50 个。
根因:连接池配置过小,且未设置合理的获取连接超时时间。当并发请求超过 50 时,多余的 150 个请求全部在 Java 线程池里排队等待数据库连接导致线程积压,最终拖垮了整个应用。
分析:
虽然等待过程并未加入到 cpu 的队列中也就是不占用 load,但是剩余队列中 50 个 cpu处理过后连接池线程会快速的加入到 load里面进而导致 CPU load一直维持在 50 个,
大量线程竞争 cpu有一定的上下文切换导致的sys cpu使用率增高由于 sql没有慢查询等性能问题所以 CPU 总体使用率并不高


【优化方案与效果】

连接池优化:根据压测结果,将 Java 端的数据库连接池最大连接数调整至 200,并合理设置 connection-timeout(如 3000ms)。
架构优化:在 Nginx 层开启 upstream keepalive,复用 Nginx 到 Java 后端的长连接,减少频繁建立 TCP 握手的开销。
最终效果:线程等待现象消失,系统 Load Average 恢复正常

posted @ 2026-05-24 20:09  fanggege  阅读(13)  评论(0)    收藏  举报