前言
热部署就是在服务器运行时重新部署项目,热加载即在在运行时重新加载 class,从而升级应用。
通常情况下在开发环境中我们使用的是热加载,因为热加载的实现的方式在 Web 容器中启动一个后台线程,定期检测相关文件的变化,如果有变化就重新加载类,这个过程不会清空 Session。而在生产环境我们一般应用的是热部署,热部署也是在 Web 应用后台线程定期检测,发现有变化就会重新加载整个 Web 应用,这种方式更加彻底会清空 Session。
# 热加载
热加载其实我们在开发过程中经常使用,例如我们使用 Idea 开发时,我们在设置页面可以进行设置,当修改文件时,我们可以选择不重启项目,选择重新加载此文件。而在 Tomcat 中也能设置,Tomcat 默认情况下是不开启热加载的。需要在 Tomcat 路径下的 Context.xml 中配置 reloadable 参数来开启这个功能。
我们演示一下 Tomcat 是如何热加载的。在 webapp 下我们新建了一个项目,里面的 Servlet 文件如下
目录结构如下
为了演示 Tomcat 运行时能修改 class 文件能够动态加载。我们分为以下三步
-
正常启动 Tomcat。输入 http://localhost:8080/mywebapp/myservlet,观察页面输出
-
在 Tomcat 启动的情况下修改 MyServlet 文件后覆盖原来的 class 文件
-
再次观察页面情况。观察页面输出是否修改
下面直接用动态图演示效果,更直观一些。
我们可以看到在 Tomcat 运行的情况下,直接替换 class 文件是能够直接生效的。那么 Tomcat 是如何做到的呢?其实我们可以自己推导一下。
-
所有的 class 文件都是交由类加载来管理的
-
如果换了 class 文件是不是只需要更换相应的类加载器重新加载就行
那么接下来我们来验证我们的结论,看一下在 Tomcat 中是如何实现热加载的。Tomcat 要监听 class 文件是否变化应该是新起了一个线程来观测。那么看到在 Context 的启动方法中,看到调用了 threadStart 的方法。
其中在后台开启周期性的任务,使用了 Java 提供的 ScheduledThreadPoolExecutor。除了能周期性执行任务以外还有线程池的功能。上面代码中调用了 scheduleWithFixedDelay 方法,第一个传入的参数就是要执行的任务。我们接下来看任务类 ContainerBackgroundProcessor 是如何实现的。
上面代码中我们可以知道具体的后台监听代码是在 backgroundProcess 方法中实现的。那么我们看 Context 容器的 backgroundProcess 方法是如何实现的。
进去 loader.backgroundProcess();中我们可以看到
我们可以发现 Tomcat 热加载的步骤
-
如果发现有文件发生变化,热加载开关开启
-
关闭 Context 容器
-
重启 Context 容器
在这个过程中,最重要的部分其实就是类加载器了。因为一个 Context 容器对应一个类加载器。所以在销毁 Context 容器的时候也连带着将其类加载器一并销毁了。Context 在重启的过程中也会创建新的类加载器来加载我们新建的文件。
# 热部署
如果还是不懂热部署是什么的,下面演示一遍应该就明白了。Tomcat 在启动的时候会将其目录下 webapp 中 war 包解压后然后封装为一个 Context 供外部访问。那么热部署就是在程序运行时,如果我们修改了 War 包中的东西。那么 Tomcat 就会删除之前的 War 包解压的文件夹,重新解压新的 War 包。
我们发现上面动图中在 Tomcat 运行时,我们修改了 War 包的信息,它就会将原来的删除然后重新生成一份。
我们从上面的动图中其实就看出了热部署和热加载的区别了。热部署是将文件夹删除然后重新解压包。那么热加载是由 Context 容器负责的。那么热部署又是由哪个容器负责呢?因为一个文件夹对应一个 Context。既然文件夹都删除了,那么肯定不是由 Context 容器负责了。那么应该就是 Context 的父容器 Host 来负责。
我们可以看到 Host 容器并没有实现自己的 backgroundProcess 方法。那么它是如何监听的呢?既然它没有实现方法,肯定是调用了父类的 backgroundProcess 方法。我们可以看到在父类的 backgroundProcess 中
可以看到周期事件的监听器。而 Host 的事件监听器是 HostConfig 类的 lifecycleEvent 方法
我们可以看 check 方法
热部署的步骤其实也可以简化为三步骤
-
检查 Host 管理下的所有 web 应用
-
如果原来的 Web 应用被删除,就将相应 Context 容器删除
-
如果有新 War 包放进来,就部署相应的 War 包
如果本文对你有帮助,别忘记给我个3连 ,点赞,转发,评论,
咱们下期见!答案获取方式:已赞 已评 已关~
学习更多知识与技巧,关注与私信博主(03)