参考文章
https://time.geekbang.org/column/article/104423
热加载的实现方式是 Web 容器启动一个后台线程,定期检测类文件的变化,如果有变化,就重新加载类,在这个过程中不会清空 Session ,一般用在开发环境。
热部署原理类似,也是由后台线程定时检测 Web 应用的变化,但它会重新加载整个 Web 应用。这种方式会清空 Session,比热加载更加干净、彻底,一般用在生产环境。
tomcat定时任务是怎么实现的?
tomcat的热加载和热部署是通过ScheduledThreadPoolExecutor 定时线程池来实现的。
bgFuture = exec.scheduleWithFixedDelay(
new ContainerBackgroundProcessor(),//要执行的Runnable
backgroundProcessorDelay, //第一次执行延迟多久
backgroundProcessorDelay, //之后每次执行间隔多久
TimeUnit.SECONDS); //时间单位
ContainerBackgroundProcessor 的任务的逻辑是:调用当前容器的 backgroundProcess 方法,以及递归调用子孙的 backgroundProcess 方法
backgroundProcess 是 Container 接口中的方法,也就是说所有类型的容器都可以实现这个方法,在这个方法里完成需要周期性执行的任务。
这样的设计意味着:我们只需要在顶层容器,也就是 Engine 容器中启动一个后台线程,那么这个线程不但会执行 Engine 容器的周期性任务,它还会执行所有子容器的周期性任务。
热加载:
默认是关闭的。作用在context上
context的backgroundProcess 方法 检查类文件是否有更新,有更新则调用
而 Context 的 reload 方法比较复杂,总结起来,主要完成了下面这些任务:
- 停止和销毁 Context 容器及其所有子容器,子容器其实就是 Wrapper,也就是说 Wrapper 里面 Servlet 实例也被销毁了。
- 停止和销毁 Context 容器关联的 Listener 和 Filter。
- 停止和销毁 Context 下的 Pipeline 和各种 Valve。
- 停止和销毁 Context 的类加载器,以及类加载器加载的类文件资源。
- 启动 Context 容器,在这个过程中会重新创建前面四步被销毁的资源。
热部署
原来的 Context 对象会整个被销毁掉,因此这个 Context 所关联的一切资源都会被销毁,包括 Session。
通过监听器 HostConfig 来实现的,check方法会做以下两件事。
- 如果原来 Web 应用目录被删掉了,就把相应 Context 容器整个销毁掉。
- 是否有新的 Web 应用目录放进来了,或者有新的 WAR 包放进来了,就部署相应的 Web 应用。
那HostConfig的方法是在哪里调用的呢?原来是在ContainerBase 的 backgroundProcess 方法实现如下
public void backgroundProcess() {
//1.执行容器中Cluster组件的周期性任务
Cluster cluster = getClusterInternal();
if (cluster != null) {
cluster.backgroundProcess();
}
//2.执行容器中Realm组件的周期性任务
Realm realm = getRealmInternal();
if (realm != null) {
realm.backgroundProcess();
}
//3.执行容器中Valve组件的周期性任务
Valve current = pipeline.getFirst();
while (current != null) {
current.backgroundProcess();
current = current.getNext();
}
//4. 触发容器的"周期事件",Host容器的监听器HostConfig就靠它来调用
fireLifecycleEvent(Lifecycle.PERIODIC_EVENT, null);
}