优化连续部署(取消职责链)

时间:2019-02-03 11:47:49

标签: java maven tomcat continuous-deployment continuous-delivery

Id喜欢改善持续投放。我正在使用Tomcat 8和Maven。

我使用mvn tomcat:redeploy部署Web应用。

tomcat documentation中,我找到了这一部分:

  

远程部署新的应用程序存档(WAR)

     

如果安装和启动成功,您将收到(...)

     

否则,响应将以FAIL开始并包含错误消息。

FAIL可能引起停顿的原因之一:

  

尝试启动新的Web应用程序时遇到异常。

所以我想在启动时抛出异常,所以我在web.xml中写道:

  

<启动时加载> 1

org.springframework.web.servlet.DispatcherServlet-Servlet。然后我写了一个单例:

@Service
public class AvoidStartupOnMissingDatabase implements SmartInitializingSingleton {

    @Override
    public void afterSingletonsInstantiated() {
        throw new RuntimeException("Do not deploy this app!");
    }
}

这会导致此Stacktrace:

java.lang.RuntimeException: Do not deploy this app!
        at xxx.AvoidStartupOnMissingDatabase.afterSingletonsInstantiated(AvoidStartupOnMissingDatabase.java:11)
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:775)
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:762)
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:480)
        at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:664)
        at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:630)
        at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:678)
        at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:549)
        at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:490)
        at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:136)
        at javax.servlet.GenericServlet.init(GenericServlet.java:158)
        at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1144)
        at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1091)
        at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:983)
        at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4962)
        at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5274)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
        at org.apache.catalina.core.StandardContext.reload(StandardContext.java:3823)
        at org.apache.catalina.startup.HostConfig.reload(HostConfig.java:1410)
        at org.apache.catalina.startup.HostConfig.checkResources(HostConfig.java:1320)
        at org.apache.catalina.startup.HostConfig.check(HostConfig.java:1648)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at org.apache.tomcat.util.modeler.BaseModelMBean.invoke(BaseModelMBean.java:300)
        at com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.invoke(DefaultMBeanServerInterceptor.java:819)
        at com.sun.jmx.mbeanserver.JmxMBeanServer.invoke(JmxMBeanServer.java:801)
        at org.apache.catalina.manager.ManagerServlet.check(ManagerServlet.java:1525)
        at org.apache.catalina.manager.ManagerServlet.deploy(ManagerServlet.java:773)
        at org.apache.catalina.manager.ManagerServlet.doPut(ManagerServlet.java:443)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:664)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at org.apache.catalina.filters.SetCharacterEncodingFilter.doFilter(SetCharacterEncodingFilter.java:108)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:613)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:81)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
        at org.apache.coyote.ajp.AjpProcessor.service(AjpProcessor.java:486)
        at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
        at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:790)
        at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1459)
        at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
        at java.lang.Thread.run(Thread.java:745)

问题

不幸的是,该应用程序已部署!

Screenshot of ci

问题

我没有通过初始化。我说的是启动时加载。 Tomcat说如果不启动就会失败。 Tomcat说(重新)部署是否可以启动。

因此,异常必须使部署失败。对吧?

编辑

我测试了tomcat-8.5.30和tomcat-8.5.37,不幸的是两个都成功了。

3 个答案:

答案 0 :(得分:4)

Iv创建了一个bug in Tomcat。开发人员引导我找到解决方案 类似于Alexandru Cojocaru。

我从Servlet转移到SerlvetContextListener,并且成功接收到部署失败的消息。

不幸的是,在此无效的部署之后,旧的应用程序重新启动。但是对svn的提交已成功取消,并且没有添加到svn-change-log中!

答案 1 :(得分:0)

Tomcat有两种选择来部署war文件:

  • 将战争复制到Web应用程序
  • http tomcat端点/ manager / text / deploy

answer

中的更多详细信息和配置

tomcat:redeploy也不用于回滚,而只是用于部署现有战争而无需再次打包。

我确定mvn tomcat:deploy插件使用 / manager / text / deploy tomcat端点部署战争文件。

假设您使用的是某些连续集成服务器(jenkins,travis等)或只是一个简单的shell脚本来调用前面的步骤,我建议您使用以下方法执行回滚:

回滚参数

在流中添加一个新的输入参数,称为:rollback_tag或previous_version。

使用Maven回滚

Maven是编译和生成war或jar文件的最佳选择。但是出于部署目的,我认为这不是最佳选择。我不希望在pom.xml中共享凭据或配置(带或不带变量):

<plugin>
   <groupId>org.codehaus.mojo</groupId>
   <artifactId>tomcat-maven-plugin</artifactId>
   <version>1.1</version>
   <configuration>
      <url>http://localhost:8080/manager/text</url>
      <server>TomcatServer</server>
      <path>/javaCodeGeeks</path>
   </configuration>
</plugin>

无论如何,如果您想使用Maven,则需要:

  • 搜索Maven插件的源代码
  • 扩展它或添加新功能,例如:
    • 从tomcat部署中捕获错误
    • 使用某些标记版本下载源代码
    • 发生错误时重新部署

再次回滚下载

步骤可以是:

  • (1)使用svn下载源代码
  • (2)执行mvn clean程序包
  • (3)执行mvn tomcat:deploy
    • 此命令必须返回退出代码
    • (3.1)如果exit_code == 0,则表明部署成功。
    • (3.2)在exit_code!= 0的情况下,将指示部署错误。继续(4)步骤
  • (4)使用svn下载源,但是在这种情况下,您必须使用rollback tag参数并重复步骤(2)和(3)

带有一些工件存储库

使用此工具,我们只需一次使用svn下载源代码。编译并成功部署后,您必须上传具有特定版本(例如1.0.0)的war或jar文件。流程中的下一步仅需要下载war / jar文件。

如果1.0.1部署出错,则只需从工件存储库下载先前的稳定版本1.0.0。 步骤可以是:

  • (1)检测开发人员的 svn commit 操作,并使用持续集成服务器或Shell脚本将war文件编译,测试并上传到工件存储库。
  • (2)从工件存储库下载war文件
  • (3)执行curl命令以上传和部署war文件。此处有更多详细信息和配置:
  • (4)如果出现错误,请从工件存储库下载war文件,但在这种情况下,您必须使用 previous_version 参数并重复步骤(3)

答案 2 :(得分:0)

部署成功。当Spring尝试加载AvoidStartupOnMissingDatabase bean时,您看到的堆栈跟踪是由应用程序运行时错误引起的。至此,该应用程序已经部署并运行。

如果要使Maven redeploy目标失败,则需要在部署期间而不是在应用程序运行时导致错误。例如,可以通过在Maven Tomcat插件配置中使用wrong URL来完成此操作。