簡體   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