Spring Boot 启动或请求卡顿从 Bean 锁、事件广播到连接池Spring Boot 卡顿时先看线程在做什么。CPU 低可能是锁、连接池或同步 I/O 等待CPU 高也可能是分配、序列化或业务循环。扩容和调堆都应放在证据之后。模拟卡顿场景与诊断决策树把 CPU、P99、吞吐和线程状态放在同一时间窗口。低 CPU 与高延迟只能提示可能存在等待仍要用线程转储、JFR 和连接池指标确认是BLOCKED、WAITING还是下游响应慢。源码级卡顿原因深度剖析通过对 Spring Boot 内部核心组件的源码拆解可以定位到以下容易引发卡顿的机制陷阱1. Spring 单例 Bean 注册锁竞争在 Spring 容器中单例 Bean 的创建与获取依赖DefaultSingletonBeanRegistry类。在其底层实现中为了保证多线程下 Bean 的单例特性采用了singletonObjectsConcurrentHashMap 配合synchronized(this.singletonObjects)互斥锁。// Spring 源码切片: DefaultSingletonBeanRegistry.java public Object getSingleton(String beanName, ObjectFactory? singletonFactory) { synchronized (this.singletonObjects) { Object singletonObject this.singletonObjects.get(beanName); if (singletonObject null) { // 走 Bean 实例化、属性填充、初始化回调流程 singletonObject singletonFactory.getObject(); this.singletonObjects.put(beanName, singletonObject); } return singletonObject; } }如果在运行期由于动态懒加载Lazy Init或原型作用域Prototype交叉引用频繁触发 Bean 实例化过程该互斥锁会导致所有尝试获取 Bean 的线程发生强烈的锁竞争使得 Worker 线程被批量挂起。2. Spring Event 同步广播的“串行阻塞”效应Spring Boot 默认提供的事件发布机制ApplicationEventPublisher是纯同步的。在SimpleApplicationEventMulticaster内部当调用multicastEvent()方法时框架会依次遍历所有匹配的ApplicationListener并同步执行onApplicationEvent()。若某个事件监听器中包含了耗时较长的操作例如发送邮件、记录远程审计日志或调用第三方 HTTP 接口主业务线程将被迫等待该监听器执行完毕。一旦第三方接口延时主线程便会直接在事件发布处发生卡顿。3. HikariCP 连接池等待与连接泄露作为 Spring Boot 默认的数据库连接池HikariCP 依靠极高的性能著称。但当连接池中的连接被耗尽时HikariPool.getConnection()会在HandOffQueue上调用poll()并等待connectionTimeout默认 30 秒。若业务代码中存在未显式关闭 ResultSet / Statement或者事务方法中包含了耗时的网络 RPC导致连接无法及时归还后续线程将全部卡在getConnection()方法上表现为极高的响应延迟。排查工具链与定位步骤在面对真实卡顿故障时应当按照以下工程步骤顺序操作步骤使用工具执行命令 / 方法诊断目的1jstackjstack -l pid threads.txt连续抓取 3 次线程栈对比TIMED_WAITING与BLOCKED状态的线程集中在哪个方法2Arthasthread -b自动找出当前阻塞其他线程最多的锁持有者线程3Arthastrace com.example.service.* getOrderDetail动态插桩输出方法内部各个子方法的精确执行耗时4Prometheushikaricp_pending_threadsMetrics监测数据库连接池当前排队等待连接的线程数量卡顿防御与优化防坑 CheckList为 ApplicationEventMulticaster 配置异步 TaskExecutor在配置类中重写applicationEventMulticasterBean注入异步线程池避免监听器阻塞主业务线程。核对事务中的外联 RPC等待 RPC 时事务可能继续占用数据库连接或持有锁放大连接池等待。能否移出事务取决于一致性要求可用本地事务 事件、Outbox 或补偿流程重画边界并验证失败和重复处理。按需开启 HikariCP 泄露监测leak-detection-threshold应高于正常事务耗时并考虑采集开销。它提示连接借出过久不等同于已经证明泄漏。注意代理内部调用同一 Bean 通过this调用带Async或Transactional的方法通常不会经过代理。需要拆分 Bean 或显式调整调用边界并写测试确认事务与异步行为。