首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >tomcat自动重新加载应用

tomcat自动重新加载应用

作者头像
编程随笔
发布2019-09-11 15:59:45
5.6K1
发布2019-09-11 15:59:45
举报
文章被收录于专栏:后端开发随笔后端开发随笔

前言

当应用配置文件发生变化时,无需重启tomcat,可以使tomcat重新加载应用。

场景

假设存在一个J2EE应用A,对应war文件名称为A.war,部署在tomcat的webapps目录下,即:CATALINA_HOME/webapps/A.war。 tomcat启动之后会将A.war解压,并在$CATALINA_HOME/webapps/目录下对应生成目录A,即:CATALINA_HOME/webapps/A。 此时,需要修改A下存在一个配置文件a_dao.xml,其中配置了一些参数,如:数据库配置。 为了使应用能够重新使用最新的配置属性,有2种方式: 其一:修改配置文件,直接重启tomcat。 其二:修改配置文件,执行命令:touch TOMCAT_HOME/webapps/A/WEB-INF/web.xml,让tomcat重新加载应用A。

原理

当然,修改配置之后重启tomcat这个方式不难理解,应用重新被部署,肯定会使用到最新的配置。 那么,对于不需要重启tomcat,而是让tomcat重新加载应用,低层的实现原理是什么呢? 首先,我们来看通过tomcat重新加载应用,我们做了什么? 我们只做了一件事情:touch TOMCAT_HOME/webapps/A/WEB-INF/web.xml。 显然,这里涉及了2个组件:touch命令和tomcat。 OK,下面我们分别解读这2个组件都做了什么事情,拨云见雾地看看这里面都发生了什么。

1.touch命令做了什么

执行了touch命令,这个命令的作用是修改文件的时间戳。

TOUCH(1)                         User Commands                        TOUCH(1)

NAME
       touch - change file timestamps

SYNOPSIS
       touch [OPTION]... FILE...

DESCRIPTION
       Update the access and modification times of each FILE to the current time.

       A FILE argument that does not exist is created empty, unless -c or -h is supplied.

什么意思?在实践中发现,touch命令会将文件的“创建时间”,“访问时间”和“修改时间”这三个时间戳都修改为当前时间。 这意味着什么呢?tomcat会认为这个文件发生了变化! 那么,是不是可以理解为一旦tomcat监测到应用的描述文件web.xml发生变化之后就会主动重新加载应用呢?

如下是一个实际的tomcat重新加载应用的输出日志。

九月 15, 2017 8:21:49 下午 org.apache.catalina.startup.HostConfig reload
信息: Reloading context [/test-javaweb]
九月 15, 2017 8:21:49 下午 org.apache.catalina.core.StandardContext reload
信息: Reloading Context with name [/test-javaweb] has started
九月 15, 2017 8:21:49 下午 org.apache.catalina.ha.session.DeltaManager stopInternal
信息: Manager [localhost#/test-javaweb] expiring sessions upon shutdown
九月 15, 2017 8:21:50 下午 org.apache.catalina.startup.TaglibUriRule body
信息: TLD skipped. URI: http://java.sun.com/jstl/core_rt is already defined
九月 15, 2017 8:21:50 下午 org.apache.catalina.startup.TaglibUriRule body
信息: TLD skipped. URI: http://java.sun.com/jstl/core is already defined
九月 15, 2017 8:21:50 下午 org.apache.catalina.startup.TaglibUriRule body
信息: TLD skipped. URI: http://java.sun.com/jsp/jstl/core is already defined
九月 15, 2017 8:21:50 下午 org.apache.catalina.startup.TaglibUriRule body
信息: TLD skipped. URI: http://java.sun.com/jstl/fmt_rt is already defined
九月 15, 2017 8:21:50 下午 org.apache.catalina.startup.TaglibUriRule body
信息: TLD skipped. URI: http://java.sun.com/jstl/fmt is already defined
九月 15, 2017 8:21:50 下午 org.apache.catalina.startup.TaglibUriRule body
信息: TLD skipped. URI: http://java.sun.com/jsp/jstl/fmt is already defined
九月 15, 2017 8:21:50 下午 org.apache.catalina.startup.TaglibUriRule body
信息: TLD skipped. URI: http://java.sun.com/jsp/jstl/functions is already defined
九月 15, 2017 8:21:50 下午 org.apache.catalina.startup.TaglibUriRule body
信息: TLD skipped. URI: http://jakarta.apache.org/taglibs/standard/permittedTaglibs is already defined
九月 15, 2017 8:21:50 下午 org.apache.catalina.startup.TaglibUriRule body
信息: TLD skipped. URI: http://jakarta.apache.org/taglibs/standard/scriptfree is already defined
九月 15, 2017 8:21:50 下午 org.apache.catalina.startup.TaglibUriRule body
信息: TLD skipped. URI: http://java.sun.com/jstl/sql_rt is already defined
九月 15, 2017 8:21:50 下午 org.apache.catalina.startup.TaglibUriRule body
信息: TLD skipped. URI: http://java.sun.com/jstl/sql is already defined
九月 15, 2017 8:21:50 下午 org.apache.catalina.startup.TaglibUriRule body
信息: TLD skipped. URI: http://java.sun.com/jsp/jstl/sql is already defined
九月 15, 2017 8:21:50 下午 org.apache.catalina.startup.TaglibUriRule body
信息: TLD skipped. URI: http://java.sun.com/jstl/xml_rt is already defined
九月 15, 2017 8:21:50 下午 org.apache.catalina.startup.TaglibUriRule body
信息: TLD skipped. URI: http://java.sun.com/jstl/xml is already defined
九月 15, 2017 8:21:50 下午 org.apache.catalina.startup.TaglibUriRule body
信息: TLD skipped. URI: http://java.sun.com/jsp/jstl/xml is already defined
九月 15, 2017 8:21:50 下午 org.chench.test.web.listener.TestWebListener contextInitialized
信息: TestWebListener contextInitialized
九月 15, 2017 8:21:50 下午 org.chench.test.web.filter.TestWebFilter init
信息: TestWebFilter context path=/test-javaweb
九月 15, 2017 8:21:50 下午 org.apache.catalina.core.StandardContext reload
信息: Reloading Context with name [/test-javaweb] is completed

经过实验发现,一旦web应用的web.xml文件的时间戳发生变化(创建时间,修改时间或访问时间发生变化),tomcat就会重新加载应用。

2.tomcat如何知道应用的web.xml发生了变化

在上述tomcat日志中存在如下信息:

九月 15, 2017 8:21:49 下午 org.apache.catalina.startup.HostConfig reload
信息: Reloading context [/test-javaweb]

追踪tomcat源码发现,这个日志信息是在org.apache.catalina.startup.HostConfig类的reload方法中打印的:

/*
* Note: If either of fileToRemove and newDocBase are null, both will be
*       ignored.
*/
private void reload(DeployedApplication app, File fileToRemove, String newDocBase) {
    if(log.isInfoEnabled())
        log.info(sm.getString("hostConfig.reload", app.name));
    ...
}

继续追踪tomcat源码发现,在org.apache.catalina.core.ContainerBase中存在如下实现:

    /**
     * Start the background thread that will periodically check for
     * session timeouts.
     */
    protected void threadStart() {

        if (thread != null)
            return;
        if (backgroundProcessorDelay <= 0)
            return;

        threadDone = false;
        String threadName = "ContainerBackgroundProcessor[" + toString() + "]";
        thread = new Thread(new ContainerBackgroundProcessor(), threadName);
        thread.setDaemon(true);
        thread.start();

    }

也就是说,Tomcat在启动时会启动一个后台线程ContainerBackgroundProcessor,用于监控web应用的配置变化。 默认情况下,该线程会每隔10秒检查一次web应用的web.xml文件的变化。 该值在server.xml中Engine元素上配置属性:backgroundProcessorDelay。

详见:http://tomcat.apache.org/tomcat-7.0-doc/config/engine.html。 实际上,org.apache.catalina.startup.HostConfig中存在如下方法:

addWatchedResources(DeployedApplication app, String docBase, Context context)

这个方法是tomcat在部署应用的时候调用的,它将应用的web.xml文件添加为监控对象。 后台线程通过检测该文件的时间戳是否发生变化,从而确定是否需要重新加载应用。

另外,需要特别注意:该特性需要配置Host元素的autoDeploy属性为true;若为false,即使应用web.xml文件发生变化,tomcat也不会重新加载应用。

<Host name="localhost"  appBase="webapps"
    unpackWARs="true" autoDeploy="true">
</Host>

因为org.apache.catalina.startup.HostConfig在check时会判断autoDeploy是否为true。

/**
 * Check status of all webapps.
 */
protected void check() {

    if (host.getAutoDeploy()) {
        // Check for resources modification to trigger redeployment
        DeployedApplication[] apps =
            deployed.values().toArray(new DeployedApplication[0]);
        for (int i = 0; i < apps.length; i++) {
            if (!isServiced(apps[i].name))
                checkResources(apps[i], false);
        }

        // Check for old versions of applications that can now be undeployed
        if (host.getUndeployOldVersions()) {
            checkUndeploy();
        }

        // Hotdeploy applications
        deployApps();
    }
}

【参考】 https://www.mulesoft.com/cn/tcat/tomcat-reload

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017-09-26 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 场景
  • 原理
    • 1.touch命令做了什么
      • 2.tomcat如何知道应用的web.xml发生了变化
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档