软件环境:springboot2.1 + spring-data-jpa+ openjdk8
问题现象
重启服务后,在用户第一次访问时,部分系统响应接口响应缓慢,有时候需要20多秒才返回,但第二次调度同一个接口则返回很快
络分析
络上有该问题的三个解释说法:
方案一:dispatcherServlet 懒加载修改
在springboot的appcation.yml 中添加如下参数即可解决
方案二:数据库链接是懒加载修改(未验证)
在springboot的appcation.yml 中添加如下参数即可解决
或者在系统启动后进行预热:在@PostConstruct方案中执行一次空查询
此种方案意图是初始化一次查询以填充缓存(orm session、mysql、redis),加快下次同样请求返回结果的速度
我使用的是jpa,并且开启了spring.jpa.open-in-view=true,orm session是每次请求重置的;也没有开启redis,解决方案对我有限
方案三:linux 下真随机数生成器修改
熵池问题:https://blog.csdn.net/wysnxzm/article/details/98482143
在java启动时增加如下参数即可
或者直接去修改文件也可
以上处理方案执行 (当前预热方案还未执行)后,我的系统并未有改善。
监测分析
基于该问题,我创建了一个AOP监测的执行耗时,监测结果是的返回几乎都在几十毫秒,与实际不符,
我然后又创建了一个拦截器监测从接到请求开始到返回的执行耗时,此处的监测结果与实际耗时比较接近,使用debug分析日志,看到有如下两种情况
-
- 部分接口从拦截器接受到请求开始间隔了很长时间才交接给进行处理
-
- 部分接口返回后,间隔了很长时间(后台还运行了很多sql查询)才返回给拦截器
情况一:查找不存在的类耗时
从linux服务器中监测的日志截取如下
/mark> 看到第3行到第4行的时间差了吗,足足耗费了7.6s
ClassNotFound的几个Class肯定是在类定义中不存在的;
查看几个查找类的命名都存在后缀,排除这个后缀后,可以找到对应的类;
是中接口方法的参数,该参数bean的继承关系如下:
分析ClassNotFound的几个Class,恰好是这几个类名+后缀
在测试过程中,使用了springboot 的不同版本(2.1x、2.2x、2.3x),openJDK的不同版本(8、11)均存在这个过程
在我本机(windows10+openjdk8)环境下,这个过程在几十毫秒内完成,不影响请求速度,在服务器(ubuntu18.4+openjdk8 )环境下,部分接口在这个过程中会花费几秒(如上日志)
目前该问题仍在进一步分析中:
1、为什么会查找类
2、为什么在linux中WebappClassLoaderBase的findClass会中断那么长时间
情况二:懒加载的耗时
? 这实际上是懒加载的问题,这个问题是老生常谈了。
? 主要解决途径如下:
-
通过DO-VO来转换封装取消懒加载属性
-
在返回前置空懒加载属性
-
通过json序列化过滤懒加载属性
需要重写接口的返回,否则你的restapi只能返回json字符串了
- 通过jpa2.1中的新特性@NamedEntityGraph来提升懒加载查询效率(将 变成 )
spring-data-jpa的默认实现并不能很好的支持第四种(需要重写dao的接口注解)
JMCP分析
针对为什么在linux中WebappClassLoaderBase的findClass会中断那么长时间问题,我在jmc中开启飞行记录器l来跟踪下性能耗时

然后我发现,在受阻线程主要的时间跳跃点在的调用
基于这个类在 络上搜索到:
https://www.jb51.cc/java/437748.html
以及他的调度类的文章
https://blog.csdn.net/dennis_zane/article/details/83161898
分析下来,这个好像是tomcat的classLoader加载jar的老坑问题…
解决方案
那么换思路:我是否可以换一个classLoader呢
在springboot中有以下两种思路:
-
打包成可执行的jar,不走tomcat的
-
更换sevlet容器
我使用思路一试验了下,我的问题消失了,证明思路是对的,我卡卡…
我分析了4天,终于搞定了,神清气爽…
解决方案可以说就是改了一个字母,将pom.xml中修改为
/mark> 还有个问题 为什么会查找类 下次再搞( 黑脸)
文章知识点与官方知识档案匹配,可进一步学习相关知识Java技能树首页概览92440 人正在系统学习中
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!