热加载和热部署,没听过?看看 Tomcat 是怎么实现的(tomcat热加载原理)

热部署就是在服务器运行时重新部署项目,热加载即在在运行时重新加载class,从而升级应用。

通常情况下在开发环境中我们使用的是热加载,因为热加载的实现的方式在Web容器中启动一个后台线程,定期检测相关文件的变化,如果有变化就重新加载类,这个过程不会清空Session。而在生产环境我们一般应用的是热部署,热部署也是在Web应用后台线程定期检测,发现有变化就会重新加载整个Web应用,这种方式更加彻底会清空Session。

热加载

热加载其实我们在开发过程中经常使用,例如我们使用Idea开发时,我们在设置页面可以进行设置,当修改文件时,我们可以选择不重启项目,选择重新加载此文件。而在Tomcat中也能设置,Tomcat默认情况下是不开启热加载的。需要在Tomcat路径下的Context.xml中配置reloadable参数来开启这个功能。

<Context reloadable="true"/>复制代码

我们演示一下Tomcat是如何热加载的。在webapp下我们新建了一个项目,里面的Servlet文件如下

public class MyServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("MyServlet 在处理 get()请求..."); PrintWriter out = response.getWriter(); response.setContentType("text/html;charset=utf-8"); out.println("<strong>>My Servlet Version1!</strong><br>"); } @Override protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { System.out.println("MyServlet 在处理 post()请求..."); PrintWriter out = response.getWriter(); response.setContentType("text/html;charset=utf-8"); out.println("<strong>>My Servlet Version1!</strong><br>"); }}复制代码

目录结构如下

-webapp -- mywebapp -- WEB-INF -- web.xml -- classes -- MyServlet.class复制代码

为了演示Tomcat运行时能修改class文件能够动态加载。我们分为以下三步

  1. 正常启动Tomcat。输入http://localhost:8080/mywebapp/myservlet,观察页面输出
  2. 在Tomcat启动的情况下修改MyServlet文件后覆盖原来的class文件
  3. 再次观察页面情况。观察页面输出是否修改

下面直接用动态图演示效果,更直观一些。

热加载和热部署,没听过?看看 Tomcat 是怎么实现的(tomcat热加载原理)

我们可以看到在Tomcat运行的情况下,直接替换class文件是能够直接生效的。那么Tomcat是如何做到的呢?其实我们可以自己推导一下。

  1. 所有的class文件都是交由类加载来管理的
  2. 如果换了class文件是不是只需要更换相应的类加载器重新加载就行

那么接下来我们来验证我们的结论,看一下在Tomcat中是如何实现热加载的。Tomcat要监听class文件是否变化应该是新起了一个线程来观测。那么看到在Context的启动方法中,看到调用了threadStart的方法。

protected void threadStart() { backgroundProcessorFuture = Container.getService(this).getServer().getUtilityExecutor() .scheduleWithFixedDelay(new ContainerBackgroundProcessor(),//要执行的Runnable backgroundProcessorDelay, //第一次执行延迟多久 backgroundProcessorDelay, //之后每次隔多久执行一次 TimeUnit.SECONDS); //时间单位 }}复制代码

其中在后台开启周期性的任务,使用了Java提供的ScheduledThreadPoolExecutor。除了能周期性执行任务以外还有线程池的功能。上面代码中调用了scheduleWithFixedDelay方法,第一个传入的参数就是要执行的任务。我们接下来看任务类ContainerBackgroundProcessor是如何实现的。

protected class ContainerBackgroundProcessor implements Runnable { @Override public void run() { // 请注意这里传入的参数是 " 宿主类 " 的实例 processChildren(ContainerBase.this); } protected void processChildren(Container container) { try { //1. 调用当前容器的 backgroundProcess 方法。 container.backgroundProcess(); //2. 遍历所有的子容器,递归调用 processChildren, // 这样当前容器的子孙都会被处理 Container[] children = container.findChildren(); for (int i = 0; i < children.length; i ) { // 这里会判断子容器如果已经启动了后台线程,那么这里就不会启动了 if (children[i].getBackgroundProcessorDelay() <= 0) { processChildren(children[i]); } } } catch (Throwable t) { ... }复制代码

上面代码中我们可以知道具体的后台监听代码是在backgroundProcess方法中实现的。那么我们看Context容器的backgroundProcess方法是如何实现的。

public void backgroundProcess() { //WebappLoader 周期性的检查 WEB-INF/classes 和 WEB-INF/lib 目录下的类文件 Loader loader = getLoader(); if (loader != null) { loader.backgroundProcess(); } ............省略}

进去loader.backgroundProcess();中我们可以看到

public void backgroundProcess() { //此处判断热加载开关是否开启和监控的文件夹中文件是否有修改 if (reloadable && modified()) { try { Thread.currentThread().setContextClassLoader (WebappLoader.class.getClassLoader()); if (context != null) { //Context重启 context.reload(); } } finally { if (context != null && context.getLoader() != null) { Thread.currentThread().setContextClassLoader (context.getLoader().getClassLoader()); } } }}

我们可以发现Tomcat热加载的步骤

  1. 如果发现有文件发生变化,热加载开关开启
  2. 关闭Context容器
  3. 重启Context容器

在这个过程中,最重要的部分其实就是类加载器了。因为一个Context容器对应一个类加载器。所以在销毁Context容器的时候也连带着将其类加载器一并销毁了。Context在重启的过程中也会创建新的类加载器来加载我们新建的文件。

热部署

如果还是不懂热部署是什么的,下面演示一遍应该就明白了。Tomcat在启动的时候会将其目录下webapp中war包解压后然后封装为一个Context供外部访问。那么热部署就是在程序运行时,如果我们修改了War包中的东西。那么Tomcat就会删除之前的War包解压的文件夹,重新解压新的War包。

热加载和热部署,没听过?看看 Tomcat 是怎么实现的(tomcat热加载原理)

我们发现上面动图中在Tomcat运行时,我们修改了War包的信息,它就会将原来的删除然后重新生成一份。

我们从上面的动图中其实就看出了热部署和热加载的区别了。热部署是将文件夹删除然后重新解压包。那么热加载是由Context容器负责的。那么热部署又是由哪个容器负责呢?因为一个文件夹对应一个Context。既然文件夹都删除了,那么肯定不是由Context容器负责了。那么应该就是Context的父容器Host来负责。

我们可以看到Host容器并没有实现自己的backgroundProcess方法。那么它是如何监听的呢?既然它没有实现方法,肯定是调用了父类的backgroundProcess方法。我们可以看到在父类的backgroundProcess中

@Override public void backgroundProcess() { . ...........省略 fireLifecycleEvent(Lifecycle.PERIODIC_EVENT, null); }

可以看到周期事件的监听器。而Host的事件监听器是HostConfig类的lifecycleEvent方法

@Override public void lifecycleEvent(LifecycleEvent event) { if (event.getType().equals(Lifecycle.PERIODIC_EVENT)) {// 周期事件 check(); } else if (event.getType().equals(Lifecycle.BEFORE_START_EVENT)) {// 开始之前事件 beforeStart(); } else if (event.getType().equals(Lifecycle.START_EVENT)) { // 开始事件 start(); } else if (event.getType().equals(Lifecycle.STOP_EVENT)) { // 结束事件 stop(); } }

我们可以看check方法

protected void check() { if (host.getAutoDeploy()) { // 检查Host下所有已经部署的web应用 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); } // 检查Web应用是否有变化 if (host.getUndeployOldVersions()) { checkUndeploy(); } // 执行部署 deployApps(); }}复制代码

热部署的步骤其实也可以简化为三步骤

  1. 检查Host管理下的所有web应用
  2. 如果原来的Web应用被删除,就将相应Context容器删除
  3. 如果有新War包放进来,就部署相应的War包

作者 | 不学无数的程序员

来源 | https://urlify.cn/Ir6Z7n

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

(0)
上一篇 2024年7月8日 下午7:06
下一篇 2024年7月8日 下午7:17

相关推荐

  • 制造型企业项目管理软件

    制造型企业项目管理软件:助力企业高效管理项目 近年来,随着市场竞争的加剧和企业业务的不断增长,制造型企业的项目管理水平越来越受到重视。项目管理软件是一种能够帮助企业高效管理项目的工…

    科研百科 2024年5月23日
    124
  • 销售业务流程管理系统

    销售业务流程管理系统:提升销售效率 随着现代商业竞争的不断加剧,企业需要不断地提高销售效率,以吸引更多的客户,增加销售额。传统的销售业务流程已经无法满足现代商业的需求,因此,销售业…

    科研百科 2024年5月26日
    74
  • 年度安全经费投入计划

    年度安全经费投入计划 随着社会经济的不断发展,企业的安全责任也越来越重大。为了保障员工和客户的安全,企业需要投入一定的经费来支持安全项目的研发、实施和评估。本文将介绍企业年度安全经…

    科研百科 2024年8月18日
    51
  • 科研项目负责人承担的主要工作

    科研项目负责人承担的主要工作 科研项目负责人是一支关键团队的成员,他们承担了许多重要的工作,从项目的启动到完成。本文将介绍科研项目负责人承担的主要工作。 首先,科研项目负责人需要承…

    科研百科 2024年10月30日
    0
  • 应急厅召开2022年度抓党建工作述职及述责述廉评议考核会议(应急局党建述职报告)

    1月29日,四川省应急管理厅组织召开2022年度抓党建工作述职及述责述廉评议考核会议,集中对厅机关各处室、各直属事业单位履行抓党建主体责任和党风廉政建设工作成效进行检验。厅党委书记…

    科研百科 2024年7月6日
    35
  • 四川小自考丨工程管理专业详细介绍(四川自考工程管理本科)

    四川小自考丨工程管理专业详细介绍(四川自考工程管理本科) 专业简介 工程管理专业是新兴的工程技术与管理交叉复合性学科。该专业培养具备管理学、经济学、信息工程、土木工程等技术的基本知…

    科研百科 2024年3月24日
    97
  • 江苏:2022年省科技计划专项资金(重点研发计划产业前瞻与关键核心技术)拟立项目名单

    近日,江苏省科学技术厅发布《2022年江苏省科技计划专项资金(重点研发计划产业前瞻与关键核心技术)拟立项目公示》。为深入贯彻省第十四次党代会精神,全面落实《江苏省“十四五”科技创新…

    科研百科 2022年7月1日
    293
  • 退休党员干部转到社区

    尊敬的社区居民们: 我是某退休党员干部,现转到社区,与居民们共同建设和谐美好的社区。 作为一名退休党员干部,我深知社区是我们党和政府联系群众的桥梁和纽带。我们的职责就是充分发挥自己…

    科研百科 2024年12月9日
    0
  • 虚拟机办公系统怎么安装(虚拟机办公系统)

    虚拟机办公系统: 让办公室变得更加高效 随着科技的不断发展,办公室的工作方式也在不断地改变。现在,越来越多的人选择使用虚拟机办公系统来提高工作效率。本文将探讨虚拟机办公系统的好处,…

    科研百科 2024年8月31日
    35
  • 项目时间管理包括

    项目时间管理包括的内容有很多,其中最重要的是确定项目的目标和范围。这可以通过与项目利益相关者交流,制定项目计划书和时间表来实现。 项目时间管理还包括跟踪项目的进度,并确保在规定的时…

    科研百科 2024年5月26日
    65