用 Arthas 定位 Spring Boot 接口的超时问题,让应用起飞( 七 )


删除swagger的jar包后问题,诡异的70+ms就消失了:
<!--pom 里删除这两个引用,这两个包时国内开发者封装的 , swagger-ui并没有提供java spring-mvc的支持包,swagger只是一个浏览器端的ui+editor --><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.9.2</version></dependency><dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger-ui</artifactId><version>2.9.2</version></dependency>那么为什么swagger会导致请求耗时呢,为什么每次请求偶读会加载swagger内部的静态资源呢?
其实这是tomcat-embed的一个bug吧,下面详细介绍一下该Bug
2.Tomcat embed Bug分析&解决源码分析过程实在太漫长,而且也不是本文的重点,所以就不介绍了,下面直接介绍下分析结果,顺便贴一张tomcat处理请求的核心类图:

用 Arthas 定位 Spring Boot 接口的超时问题,让应用起飞

文章插图
(1) 为什么每次请求会加载Jar包内的静态资源
关键在于org.apache.catalina.mapper.Mapper#internalMapWrapper这个方法,该版本下处理请求的方式有问题 , 导致每次都校验静态资源 。
(2) 为什么连续请求不会出现问题
【用 Arthas 定位 Spring Boot 接口的超时问题,让应用起飞】因为Tomcat对于这种静态资源的解析是有缓存的,优先从缓存查找,缓存过期后再重新解析 。具体参考org.apache.catalina.webresources.Cache,默认过期时间ttl是5000ms 。
(3) 为什么本地不会复现
其实确切的说,是通过spring-boot打包插件后不能复现 。由于启动方式的不同,tomcat使用了不同的类去处理静态资源,所以没问题 。
(4) 如何解决
升级tomcat-embed版本即可 。
当前出现Bug的版本为:
  • spring-boot:2.0.2.RELEASE,内置的tomcat embed版本为8.5.31
  • 升级tomcat embed版本至8.5.40+即可解决此问题,新版本已经修复了
3.通过替换springboot pom properties方式如果项目是maven是继承的springboot,即parent配置为springboot的 , 或者dependencyManagement中import spring boot包的:
<parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.0.2.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent>pom中直接覆盖properties即可:
<properties><tomcat.version>8.5.40</tomcat.version></properties>升级spring boot版本:springboot 2.1.0.RELEASE中的tomcat embed版本已经大于8.5.31了,所以直接将springboot升级至该版本及以上版本就可以解决此问题 。




推荐阅读