案例二:大促高峰期全站接口响应卡顿(系统与配置层面)
【故障现象】
在大促活动高峰期,网站整体响应变得极其缓慢,不仅订单接口,连简单的商品列表接口也出现大量超时,且服务器 CPU 使用率并不高。
在大促活动高峰期,网站整体响应变得极其缓慢,不仅订单接口,连简单的商品列表接口也出现大量超时,且服务器 CPU 使用率并不高。
【全链路排查与指标定位】
-
Linux 操作系统层(排除资源饱和)
使用top和iostat命令观察服务器状态。- 指标发现:CPU 使用率仅 40%,磁盘 I/O 的
%util也不高,但系统的 Load Average(平均负载)却飙到了 50 以上。 - 结论:CPU 空闲但负载极高,说明有大量的线程处于 “不可中断睡眠(D状态)” 或 “等待(Waiting)” 状态,通常意味着应用在等待某些外部资源(如数据库连接、锁)。
- 指标发现:CPU 使用率仅 40%,磁盘 I/O 的
-
Java 应用层(定位线程阻塞)
使用jstack <pid>导出 Java 进程的线程堆栈,或者通过 Arthas 的thread -n 5查看最忙/阻塞的线程。- 指标发现:发现大量业务线程的状态为
WAITING (parking),且堆栈信息都卡在DruidDataSource.getConnection(获取数据库连接)这一步。 - 关联排查:检查 JVM 的 GC 日志,发现 Full GC 频率并不高,排除了内存溢出导致的卡顿。
- 指标发现:发现大量业务线程的状态为
-
中间件与数据库层(定位连接池瓶颈)
结合 Java 应用的配置文件和 MySQL 的状态进行交叉验证。- 指标发现:Java 应用的数据库连接池(如 HikariCP 或 Druid)配置的
maximum-pool-size为 50,而当前并发请求量达到了 200。同时,通过ss -s或netstat发现应用服务器与 MySQL 之间的ESTABLISHED连接数死死卡在 50 个。 - 根因:连接池配置过小,且未设置合理的获取连接超时时间。当并发请求超过 50 时,多余的 150 个请求全部在 Java 线程池里排队等待数据库连接,导致线程积压,最终拖垮了整个应用。
- 指标发现:Java 应用的数据库连接池(如 HikariCP 或 Druid)配置的
【优化方案与效果】
- 连接池优化:根据压测结果,将 Java 端的数据库连接池最大连接数调整至 200,并合理设置
connection-timeout(如 3000ms)。 - 架构优化:在 Nginx 层开启
upstream keepalive,复用 Nginx 到 Java 后端的长连接,减少频繁建立 TCP 握手的开销。 - 最终效果:线程等待现象消失,系统 Load Average 恢复正常,高峰期接口错误率从 15% 降至 0.2%。
