Java Spring Boot API 10%请求响应超3秒 如何优化实现稳定响应
可能的诱因
- 数据库层面长尾问题:虽然只有2-3次数据库调用,90%的场景下执行快,不代表没有偶发慢查询。最常见的是参数倾斜导致的索引失效:部分请求的查询参数关联的数据量远高于平均水平,或者参数值没有命中索引,查询耗时陡增;也可能是数据库锁等待,10%的请求刚好命中热点行的写锁阻塞,或者数据库连接池资源不足,请求拿不到连接陷入排队,这类等待不会导致JVM CPU、内存出现尖刺,很容易被常规监控漏掉。
- JVM STW停顿:JVM监控粒度如果是分钟级,很容易漏掉秒级的GC停顿,比如G1的Remark阶段、CMS的重新标记阶段、甚至偶发的Full GC,都会导致所有业务线程暂停,对应的请求响应时间直接拉长,这类问题从常规的内存使用率曲线看不到异常,需要单独看GC日志。
- 框架层面排队阻塞:Tomcat工作线程池队列、Spring MVC拦截器链的偶发阻塞都可能导致长尾,比如突发流量下工作线程被占满,新请求进入队列等待,等待时间会直接算入响应耗时;如果日志配置为同步刷盘,偶发磁盘IO高的时候,写日志操作也会阻塞业务线程,导致响应变慢。
- 网络波动:应用到数据库的跨机房网络抖动、TCP丢包重传,也会导致小比例请求的数据库调用耗时变长。
优化方案
- 数据库侧优化:开启数据库慢查询日志,阈值设置为1s,抓取出慢请求对应的SQL,查看执行计划确认是否命中索引,针对参数倾斜的场景可以做热点数据预缓存,或者拆分大表;调整Hikari连接池参数,
spring.datasource.hikari.maximum-pool-size建议设置为「CPU核心数*2 + 有效磁盘数」,避免连接资源不足排队;热点数据的更新用乐观锁替代悲观锁,减少锁等待时间。 - JVM优化:开启GC日志打印,确认是否有超过1s的STW停顿,如果使用G1 GC可以调整
-XX:MaxGCPauseMillis参数降低最大停顿目标,适当调大年轻代大小减少YGC频率;JDK21+版本可以开启虚拟线程,大幅降低线程上下文切换开销。 - 框架侧优化:调整Tomcat线程池配置,根据实际压测结果调整
server.tomcat.max-threads和server.tomcat.accept-count,避免请求队列过长;日志组件改用异步刷盘,配置Logback的AsyncAppender,避免日志IO阻塞业务线程。 - 缓存优化:接入Caffeine本地缓存,将热点查询结果缓存1-5s,无需每次请求都访问数据库,直接从内存返回结果,大幅降低长尾请求占比。
内容的提问来源于stack exchange,提问作者Nobody
相关产品推荐
相关产品推荐

