自动部署中Tomcat被异常卡死的处理办法

在工作中自开发了一套java系统,这个系统的功能是通过quartz定时生成报表,用户通过登录系统来查看报表。IBM公司也有这样一个系统。
在开发这个系统的时候为了满足快速迭代的要求,需要实现自动打包部署的功能,因为我用jenkins作为部署平台来实现。jenkins按照如下方法思路进行:

  1. 先用jenkins自带功能到代码服务器抓取代码。
  2. 调用maven进行编译。
  3. 调用ant脚本进行备份部署包和修改部署包的名称。
  4. 使用jenkins自带功能部署到远程tomcat服务器上。

但是每次在部署远程tomcat服务器时总是出现如下问题:

Deploying C:\Users\Administrator\.jenkins\workspace\PLMReport_TST\PLMReport\target\Report.war to container Tomcat 7.x Remote
  Redeploying [C:\Users\Administrator\.jenkins\workspace\PLMReport_TST\PLMReport\target\Report.war]
  Undeploying [C:\Users\Administrator\.jenkins\workspace\PLMReport_TST\PLMReport\target\Report.war]
ERROR: Build step failed with exception
org.codehaus.cargo.container.ContainerException: Failed to undeploy [C:\Users\Administrator\.jenkins\workspace\PLMReport_TST\PLMReport\target\Report.war]
    at org.codehaus.cargo.container.tomcat.internal.AbstractTomcatManagerDeployer.undeploy(AbstractTomcatManagerDeployer.java:140)
    at org.codehaus.cargo.container.tomcat.internal.AbstractTomcatManagerDeployer.redeploy(AbstractTomcatManagerDeployer.java:178)
    at hudson.plugins.deploy.CargoContainerAdapter.deploy(CargoContainerAdapter.java:73)
    at hudson.plugins.deploy.CargoContainerAdapter$1.invoke(CargoContainerAdapter.java:116)
    at hudson.plugins.deploy.CargoContainerAdapter$1.invoke(CargoContainerAdapter.java:103)
    at hudson.FilePath.act(FilePath.java:990)
    at hudson.FilePath.act(FilePath.java:968)
    at hudson.plugins.deploy.CargoContainerAdapter.redeploy(CargoContainerAdapter.java:103)
    at hudson.plugins.deploy.DeployPublisher.perform(DeployPublisher.java:61)
    at hudson.tasks.BuildStepMonitor$3.perform(BuildStepMonitor.java:45)
    at hudson.model.AbstractBuild$AbstractBuildExecution.perform(AbstractBuild.java:782)
    at hudson.model.AbstractBuild$AbstractBuildExecution.performAllBuildSteps(AbstractBuild.java:723)
    at hudson.maven.MavenModuleSetBuild$MavenModuleSetBuildExecution.post2(MavenModuleSetBuild.java:1047)
    at hudson.model.AbstractBuild$AbstractBuildExecution.post(AbstractBuild.java:668)
    at hudson.model.Run.execute(Run.java:1763)
    at hudson.maven.MavenModuleSetBuild.run(MavenModuleSetBuild.java:531)
    at hudson.model.ResourceController.execute(ResourceController.java:98)
    at hudson.model.Executor.run(Executor.java:410)
Caused by: org.codehaus.cargo.container.tomcat.internal.TomcatManagerException: FAIL - Context /Report is defined in server.xml and may not be undeployed

    at org.codehaus.cargo.container.tomcat.internal.TomcatManager.invoke(TomcatManager.java:566)
    at org.codehaus.cargo.container.tomcat.internal.TomcatManager.invoke(TomcatManager.java:480)
    at org.codehaus.cargo.container.tomcat.internal.TomcatManager.undeploy(TomcatManager.java:420)
    at org.codehaus.cargo.container.tomcat.Tomcat7xRemoteDeployer.performUndeploy(Tomcat7xRemoteDeployer.java:62)
    at org.codehaus.cargo.container.tomcat.internal.AbstractTomcatManagerDeployer.undeploy(AbstractTomcatManagerDeployer.java:130)
    ... 17 more
org.codehaus.cargo.container.tomcat.internal.TomcatManagerException: FAIL - Context /Report is defined in server.xml and may not be undeployed

    at org.codehaus.cargo.container.tomcat.internal.TomcatManager.invoke(TomcatManager.java:566)
    at org.codehaus.cargo.container.tomcat.internal.TomcatManager.invoke(TomcatManager.java:480)
    at org.codehaus.cargo.container.tomcat.internal.TomcatManager.undeploy(TomcatManager.java:420)
    at org.codehaus.cargo.container.tomcat.Tomcat7xRemoteDeployer.performUndeploy(Tomcat7xRemoteDeployer.java:62)
    at org.codehaus.cargo.container.tomcat.internal.AbstractTomcatManagerDeployer.undeploy(AbstractTomcatManagerDeployer.java:130)
    at org.codehaus.cargo.container.tomcat.internal.AbstractTomcatManagerDeployer.redeploy(AbstractTomcatManagerDeployer.java:178)
    at hudson.plugins.deploy.CargoContainerAdapter.deploy(CargoContainerAdapter.java:73)
    at hudson.plugins.deploy.CargoContainerAdapter$1.invoke(CargoContainerAdapter.java:116)
    at hudson.plugins.deploy.CargoContainerAdapter$1.invoke(CargoContainerAdapter.java:103)
    at hudson.FilePath.act(FilePath.java:990)
    at hudson.FilePath.act(FilePath.java:968)
    at hudson.plugins.deploy.CargoContainerAdapter.redeploy(CargoContainerAdapter.java:103)
    at hudson.plugins.deploy.DeployPublisher.perform(DeployPublisher.java:61)
    at hudson.tasks.BuildStepMonitor$3.perform(BuildStepMonitor.java:45)
    at hudson.model.AbstractBuild$AbstractBuildExecution.perform(AbstractBuild.java:782)
    at hudson.model.AbstractBuild$AbstractBuildExecution.performAllBuildSteps(AbstractBuild.java:723)
    at hudson.maven.MavenModuleSetBuild$MavenModuleSetBuildExecution.post2(MavenModuleSetBuild.java:1047)
    at hudson.model.AbstractBuild$AbstractBuildExecution.post(AbstractBuild.java:668)
    at hudson.model.Run.execute(Run.java:1763)
    at hudson.maven.MavenModuleSetBuild.run(MavenModuleSetBuild.java:531)
    at hudson.model.ResourceController.execute(ResourceController.java:98)
    at hudson.model.Executor.run(Executor.java:410)
Build step 'Deploy war/ear to a container' marked build as failure

经过服务器部门检查,tomcat配置和运行正常。后来一直以为是jenkins远程部署插件有bug,今天在学习多线程时突然想到问题原因如下:

这个报表的架构是spring+quartz+hibernate.系统部署在tomcat服务器上。
当tomcat启动时,会启动quartz的主调度线程,这个调度线程会执行定时任务。实现方式是通过线程池。因此在tomcat关闭时,quartz的任务线程并未关闭,所以导致tomcat一直在等待quartz任务线程结束,当等待超过一定时长,远程部署失败。

在网上查的资料有如下方法解决:
http://blog.sina.com.cn/s/blog_6f7d179e01017ox2.html

但是如果关闭任务线程时间过长,还是会导致远程部署失败。因此我提供如下方法:

使用独立进程来启动quartz的主线程。例如通过shell启动quartz的入口类。在spring中不要集成quartz。这样tomcat在启动关闭时,就不会受到quartz影响。

你可能感兴趣的:(杂记)