我已经构建了一个Web应用程序,该应用程序在CentOS 7.2上使用SpringBoot v1.3.6.RELEASE Tomcat 8.0.36 Java 1.8u101
该Web应用程序也是SOAP客户端,它调出另一个Web应用程序。(JAX-WS RI 2.2.9)如果应用程序保持空闲状态15秒钟,则第一个Web服务调用将停顿2秒钟。似乎停滞发生在oacloader.WebappClassLoaderBase中。
闲置15秒后
16:02:36.165:委托给父类加载器org.springframework.boot.loader.LaunchedURLClassLoader@45283ce2 16:02:36.170:搜索本地存储库 16:02:36.170:findResource(META-INF / services / javax.xml.soap.MetaFactory) 16:02:38.533:->找不到资源,返回null 16:02:38.533:->找不到资源,返回null
16:02:36.165:委托给父类加载器org.springframework.boot.loader.LaunchedURLClassLoader@45283ce2
16:02:36.170:搜索本地存储库
16:02:36.170:findResource(META-INF / services / javax.xml.soap.MetaFactory)
16:02:38.533:->找不到资源,返回null
下一个请求没有空闲时间
16:07:09.981:委托给父类加载器org.springframework.boot.loader.LaunchedURLClassLoader@45283ce2 16:07:09.984:搜索本地存储库 16:07:09.985:findResource(META-INF / services / javax.xml.soap.MetaFactory) 16:07:09.986:->找不到资源,返回null 16:07:09.986:->找不到资源,返回null 16:07:09.988:findResources(META-INF / services
16:07:09.981:委托给父类加载器org.springframework.boot.loader.LaunchedURLClassLoader@45283ce2
16:07:09.984:搜索本地存储库
16:07:09.985:findResource(META-INF / services / javax.xml.soap.MetaFactory)
16:07:09.986:->找不到资源,返回null
16:07:09.988:findResources(META-INF / services
以上所有消息都是由oacloader.WebappClassLoaderBase产生的,并且显然是由JAX-WS RI的ClientSOAPHandlerTube.processRequest引起的。
您会注意到第一个通话耗时超过2秒,但随后的通话仅需毫秒。我想知道是否有人经历过这种行为?
可能的解决方案:是否可以将tomcat在springboot中使用的类加载器更改为使用ParallelWebappClassLoader
也许这是类加载器上可重载标志的产物,但我看不到如何在springboot中更改该标志。
使用Jetty作为容器运行时,不会发生这种情况。
最终解决方案:( 感谢Gergely Bacso)
@Bean public EmbeddedServletContainerCustomizer servletContainerCustomizer() { return new EmbeddedServletContainerCustomizer() { @Override public void customize(ConfigurableEmbeddedServletContainer container) { if (container instanceof TomcatEmbeddedServletContainerFactory) { customizeTomcat((TomcatEmbeddedServletContainerFactory) container); } } private void customizeTomcat(TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory) { tomcatEmbeddedServletContainerFactory.addContextCustomizers(new TomcatContextCustomizer() { @Override public void customize(Context cntxt) { cntxt.setReloadable(false); } }); } }; }
实际上,您的发现相当不错,并且您已经有90%回答了您的问题。这两个事实:
表明这将是与Tomcat相关的问题,因为:
o.a.c.
org.apache.catalina
您还观察到,此问题是在15秒钟的空闲时间后发生的。这完全符合Tomcat的默认checkInterval设置,即:
checkInterval
如果已将可重载设置为true,则检查修改的类和资源之间的秒数。默认值为15秒。
简而言之:当前您的reloadable标志为ON,并且Tomcat尝试重新加载您的类,这在开发过程中很方便,但是在任何其他情况下都是不可接受的。但是,关闭它的方法不是通过Spring- boot。
reloadable
解决方案: 您需要找到您的context.xml / server.xml,您将在其中找到如下所示的Context定义:
Context
<Context ... reloadable="true">
删除reloadable标志,您已经解决了问题。该文件本身可以位于$ CATALINE_HOME / conf的$ CATALINA_BASE / conf中,但实际上,要查找是否要使用某些IDE为您管理Tomcat,这些位置可能有些棘手。
如果使用Spring-boot嵌入式Tomcat:
您可以用来操纵Tomcat设置的类是:EmbeddedServletContainerCustomizer。
EmbeddedServletContainerCustomizer
通过此操作,您可以添加TomcatContextCustomizer(addContextCustomizers),以便可以调用setReloadable上下文本身。
TomcatContextCustomizer
addContextCustomizers
setReloadable
我没有看到任何原因使Spring-boot需要将此标志设置为true。