gpt4 book ai didi

java - Springboot嵌入式Tomcat类加载器缓慢

转载 作者:IT老高 更新时间:2023-10-28 13:47:23 26 4
gpt4 key购买 nike

我已经构建了一个使用SpringBoot v1.3.6.RELEASE Tomcat 8.0.36Java 1.8u101在 CentOS 7.2 上

Web 应用程序也是调用另一个 Web 应用程序的 SOAP 客户端。(JAX-WS RI 2.2.9)如果应用程序保持空闲 15 秒,则第一个 Web 服务调用会停止近 2 秒。似乎停顿发生在 o.a.c.loader.WebappClassLoaderBase 中。

空闲 15 秒后

16:02:36.165 : Delegating to parent classloader org.springframework.boot.loader.LaunchedURLClassLoader@45283ce2

16:02:36.170 : Searching local repositories

16:02:36.170 : findResource(META-INF/services/javax.xml.soap.MetaFactory)

16:02:38.533 : --> Resource not found, returning null

16:02:38.533 : --> Resource not found, returning null

下一个请求没有空闲时间

16:07:09.981 : Delegating to parent classloader org.springframework.boot.loader.LaunchedURLClassLoader@45283ce2

16:07:09.984 : Searching local repositories

16:07:09.985 : findResource(META-INF/services/javax.xml.soap.MetaFactory)

16:07:09.986 : --> Resource not found, returning null

16:07:09.986 : --> Resource not found, returning null

16:07:09.988 : findResources(META-INF/services

上述所有消息均由 o.a.c.loader.WebappClassLoaderBase 产生,它们显然是由来自 JAX-WS RI 的 ClientSOAPHandlerTube.processRequest 引起的。

您会注意到第一次调用需要 2 秒以上,但后续调用只需要几毫秒。我想知道是否有人经历过这种行为?

可能的解决方案:是否可以将springboot中tomcat使用的类加载器改成使用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% 的问题。这两个事实:

  1. “似乎停顿发生在 o.a.c.loader.WebappClassLoaderBase”
  2. “当使用 Jetty 作为容器运行时,不会发生这种情况。”

表明这将是一个与 Tomcat 相关的问题,因为:

  1. o.a.c. 代表 org.apache.catalina
  2. 您的代码在另一个容器上运行良好。 ( jetty )

您还观察到,问题是在 15 秒的空闲时间后发生的。这完美对应了Tomcat默认的checkInterval设置,即:

The number of seconds between checks for modified classes and resources, if reloadable has been set to true. The default is 15 seconds.

简而言之:当前您的 reloadable 标志为 ON,并且 Tomcat 尝试重新加载您的类,这在开发过程中很方便,但在任何其他情况下都是 Not Acceptable 。关闭它的方法不是通过 Spring-boot。

解决方案:
您需要找到您的 context.xml/server.xml,您将在其中找到您的 Context 定义如下:

<Context ... reloadable="true">

去掉 reloadable 标志,问题就解决了。该文件本身可以位于 $CATALINE_HOME/conf 的 $CATALINA_BASE/conf 中,但实际上,如果您使用某些 IDE 为您管理 Tomcat,这些位置可能会有点难以找到。

如果是带有 Spring-boot 的嵌入式 Tomcat:

你可以使用的类 manipulate Tomcat settings是:EmbeddedServletContainerCustomizer.

通过这个你可以添加一个 TomcatContextCustomizer (addContextCustomizers) 以便你可以在上下文本身上调用 setReloadable

我看不出 Spring-boot 需要这个标志的任何理由。

关于java - Springboot嵌入式Tomcat类加载器缓慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39234159/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com