繁体   English   中英

如果 spring-boot 上下文部署失败,Tomcat 多上下文部署将停止整个过程

[英]Tomcat multi-context deployment stops whole process if spring-boot context fails to deploy

我有一个非常具体的 Tomcat 配置,我不想更改它,我正在为这个特定配置寻找解决方案。

我已经在 Tomcat 中的conf/server.xml文件中声明了多个上下文 ( <Context> ) 进行部署,我知道不建议这样做。 我的问题是,如果其中一个部署失败,整个 Tomcat 进程将停止,从而终止已成功启动的应用程序的 rest。 这种行为是预期的吗? 是否有属性或方法可以防止这种情况并模拟不同上下文声明的行为,类似于使用context.xml文件?

我得到的错误如下:

ConfigServletWebServerApplicationContext:上下文初始化期间遇到异常

使用此堆栈跟踪(对于 Tomcat 版本 8.5.24):

SEVERE [Catalina-startStop-1] org.apache.catalina.core.ContainerBase.startInternal A child container failed during start
 java.util.concurrent.ExecutionException: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/auth-service]]
        at java.util.concurrent.FutureTask.report(FutureTask.java:122)
        at java.util.concurrent.FutureTask.get(FutureTask.java:192)
        at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:939)
        at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:872)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1419)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1409)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)
Caused by: org.apache.catalina.LifecycleException: Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/auth-service]]
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:167)
        ... 6 more
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'authenticationController': Injection of autowired dependencies failed; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'app.client-html.context' in value "${app.client-html.context}"
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:405)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1415)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:608)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:531)
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:944)
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:925)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:588)
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:144)
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:767)
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759)
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:426)
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:326)
        at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.run(SpringBootServletInitializer.java:173)
        at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.createRootApplicationContext(SpringBootServletInitializer.java:153)
        at org.springframework.boot.web.servlet.support.SpringBootServletInitializer.onStartup(SpringBootServletInitializer.java:95)
        at org.springframework.web.SpringServletContainerInitializer.onStartup(SpringServletContainerInitializer.java:174)
        at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5196)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
        ... 6 more
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'app.client-html.context' in value "${app.client-html.context}"
        at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:178)
        at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:124)
        at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:239)
        at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:210)
        at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.lambda$processProperties$0(PropertySourcesPlaceholderConfigurer.java:175)
        at org.springframework.beans.factory.support.AbstractBeanFactory.resolveEmbeddedValue(AbstractBeanFactory.java:931)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1308)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1287)
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:640)
        at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119)
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399)
        ... 27 more

示例配置:

<Host name="localhost" unpackWARs="true" autoDeploy="true">
    <Context docBase="../../app-that-works" path="/itworks"/>
    <Context docBase="../../app-that-fails" path="/itfails"/>
</Host>

重要提示:失败的应用程序是 spring-boot 应用程序,它被打包为 a.war 文件并在普通 tomcat 中运行,而不是嵌入式 tomcat 方式。 这很重要,因为这些应用程序似乎具有这种行为......

免责声明:我指的是普通 Tomcat,而不是spring 引导或嵌入式 tomcat 等。我不是在寻找这样的解决方案,只是解决这个特定问题。

基本上:

  • server.xml中配置的任何组件的start阶段(参见LifeCycle )的异常会导致服务器退出。 但是,某些异常(例如失败的ServletContextListener )不会传播。
  • 在运行时添加的组件的错误,不会导致服务器退出。

如果您不希望整个服务器停止,当上下文无法启动时,请使用自动部署:为server.xml中定义的每个上下文创建文件$CATALINA_BASE/conf/<engine_name>/<host_name>/<context_path>.xml内容:

<Context docBase="/path/to/application" />

在您的情况下,您需要创建$CATALINA_BASE/conf/Catalina/localhost/itworks.xml$CATALINA_BASE/conf/Catalina/localhost/itfails.xml 请参阅 Tomcat 对 XML 描述符的命名约定的命名。

编辑:您的堆栈跟踪表明我们可能正在处理 Tomcat 或 Spring 错误:

  • 一方面, StandardContext期望ServletContainerInitializer仅抛出ServletException (参见源代码),让所有未经检查的异常通过。 请注意,同时捕获并记录来自ServletContextListener的所有异常(参见源代码)。

  • 另一方面,Spring 的SpringServletContainerInitializer可能应该将所有未经检查的异常包装到ServletException中。

在您的情况下发生的情况是未经检查的异常一直到StandardContext并被重新抛出为LifecycleException停止服务器。 无论如何,设置:

<Context throwOnFailure="false" ... />

应该阻止 Tomcat 传播异常。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM