用 Arthas 定位 Spring Boot 接口的超时问题,让应用起飞( 六 )
发现了一个值得暂停思考的点:
+---[min=0.004452ms,max=34.479307ms,total=74.206249ms,count=31] org.apache.catalina.webresources.TomcatJarInputStream:getNextJarEntry() #117
这行代码加载了31次,一共耗时74ms;从名字上看 , 应该是tomcat加载jar包时的耗时,那么是加载了31个jar包的耗时,还是加载了jar包内的某些资源31次耗时呢?
TomcatJarInputStream这个类源码的注释写到:
The purpose of this sub-class is to obtain references to the JarEntry objects for META-INF/ and META-INF/MANIFEST.MF that are otherwise swallowed by the JarInputStream implementation.大概意思也就是,获取jar包内META-INF/,META-INF/MANIFEST的资源,这是一个子类 , 更多的功能在父类JarInputStream里 。
其实看到这里大概也能猜到问题了,tomcat加载jar包内META-INF/,META-INF/MANIFEST的资源导致的耗时 , 至于为什么连续请求不会耗时,应该是tomcat的缓存机制(下面介绍源码分析)不着急定位问题,试着通过Arthas最终定位问题细节 , 继续手动深入trace
[arthas@24851]$ trace org.apache.catalina.webresources.TomcatJarInputStream *Press Q or Ctrl+C to abort.Affect(class-cnt:1 , method-cnt:4) cost in 44 ms.`---ts=2019-09-14 21:37:47;thread_name=http-nio-7744-exec-5;id=14;is_daemon=true;priority=5;TCCL=org.springframework.boot.loader.LaunchedURLClassLoader@20ad9418`---[0.234952ms] org.apache.catalina.webresources.TomcatJarInputStream:createZipEntry()+---[0.039455ms] java.util.jar.JarInputStream:createZipEntry() #43`---[0.007827ms] java.lang.String:equals() #44`---ts=2019-09-14 21:37:47;thread_name=http-nio-7744-exec-5;id=14;is_daemon=true;priority=5;TCCL=org.springframework.boot.loader.LaunchedURLClassLoader@20ad9418`---[0.050222ms] org.apache.catalina.webresources.TomcatJarInputStream:createZipEntry()+---[0.001889ms] java.util.jar.JarInputStream:createZipEntry() #43`---[0.001643ms] java.lang.String:equals() #46#这里一共31个trace日志,删减了剩下的
从方法名上看,还是加载资源之类的意思 。都已经到jdk源码了,这时候来看一下TomcatJarInputStream这个类的源码:/*** Creates a new <code>JarEntry</code> (<code>ZipEntry</code>) for the* specified JAR file entry name. The manifest attributes of* the specified JAR file entry name will be copied to the new* <CODE>JarEntry</CODE>.** @param name the name of the JAR/ZIP file entry* @return the <code>JarEntry</code> object just created*/protected ZipEntry createZipEntry(String name) {JarEntry e = new JarEntry(name);if (man != null) {e.attr = man.getAttributes(name);}return e;}
这个createZipEntry有个name参数,从注释上看,是jar/zip文件名 , 如果能得到文件名这种关键信息,就可以直接定位问题了;还是通过Arthas , 使用watch命令,动态监测方法调用数据1.watch方法执行数据观测
让你能方便的观察到指定方法的调用情况 。能观察到的范围为:返回值、抛出异常、入参,通过编写 OGNL 表达式进行对应变量的查看 。
watch 该方法的入参:
[arthas@24851]$ watchorg.apache.catalina.webresources.TomcatJarInputStream createZipEntry "{params[0]}"Press Q or Ctrl+C to abort.Affect(class-cnt:1 , method-cnt:1) cost in 27 ms.ts=2019-09-14 21:51:14; [cost=0.14547ms] result=@ArrayList[@String[META-INF/],]ts=2019-09-14 21:51:14; [cost=0.048028ms] result=@ArrayList[@String[META-INF/MANIFEST.MF],]ts=2019-09-14 21:51:14; [cost=0.046071ms] result=@ArrayList[@String[META-INF/resources/],]ts=2019-09-14 21:51:14; [cost=0.033855ms] result=@ArrayList[@String[META-INF/resources/swagger-ui.html],]ts=2019-09-14 21:51:14; [cost=0.039138ms] result=@ArrayList[@String[META-INF/resources/webjars/],]ts=2019-09-14 21:51:14; [cost=0.033701ms] result=@ArrayList[@String[META-INF/resources/webjars/springfox-swagger-ui/],]ts=2019-09-14 21:51:14; [cost=0.033644ms] result=@ArrayList[@String[META-INF/resources/webjars/springfox-swagger-ui/favicon-16x16.png],]ts=2019-09-14 21:51:14; [cost=0.033976ms] result=@ArrayList[@String[META-INF/resources/webjars/springfox-swagger-ui/springfox.css],]ts=2019-09-14 21:51:14; [cost=0.032818ms] result=@ArrayList[@String[META-INF/resources/webjars/springfox-swagger-ui/swagger-ui-standalone-preset.js.map],]ts=2019-09-14 21:51:14; [cost=0.04651ms] result=@ArrayList[@String[META-INF/resources/webjars/springfox-swagger-ui/swagger-ui.css],]ts=2019-09-14 21:51:14; [cost=0.034793ms] result=@ArrayList[@String[META-INF/resources/webjars/springfox-swagger-ui/swagger-ui.js.map],
这下直接看到了具体加载的资源名 , 这么熟悉的名字:swagger-ui,一个国外的rest接口文档工具,又有国内开发者基于swagger-ui做了一套spring mvc的集成工具,通过注解就可以自动生成swagger-ui需要的接口定义json文件,用起来还比较方便,就是侵入性较强 。
推荐阅读
- Spark入门指南:从基础概念到实践应用全解析
- MySQL的自增id会用完吗?用完怎么办
- 巧用 Redis,实现微博 Feed 流功能!
- 用IntelliJ IDEA进行前端开发
- 暴击联盟传世脚本怎么用 斩魔无双传世手游脚本下载攻略
- 现在的城镇职工养老保险,还能够一次性补缴15年的费用吗?
- 什么是葡萄酒的有机酸?有什么作用?
- 生活清洁小妙招全部,实用清洁小妙招有哪些
- 华为手机输入这3个代码,让手机更流畅,用3年也不卡顿
- 奇亚籽可以用热水冲泡吗有毒吗 奇亚籽可以用热水冲泡吗