Tomcat 热部署实现方式源码分析总结

断了今生、忘了曾经 提交于 2019-12-03 06:24:56

研究了一下tomcat的类的热部署的源码实现,总结沉淀一下。Tomat实现热部署主要有两种机制:

(1) 一种是类似于Servlet这种类的热部署即在WEB-INF/class目录下的类:实现方式可以概括为在容器启动的时候起一条后台线程,定时的检测类文件的时间戳变化,如果类的时间戳变掉了,则调用容器的reload的方法,将类重新载入。

那么具体的分析一下:

tomcat用来加载servlet的类加载器是WebappClassLoader,但热部署的逻辑不是在这个类加载器里,而是封装在了外围的WebappLoader里面(WebappClassLoader 是WebappLoader的成员变量)。WebappLoader作为一个加载器,其实现了Loader接口,loader接口中定义了两个和热部署密切相关的方法即modified方法和backgroundProcess方法。Modified方法关联了载入器中资源的变化情况,而backgroundProcess则定义了后台线程定时扫描时具体要执行的逻辑。

    Tomcat的启动具体可以分解为各级容器的启动(即:Engine,host,context 注意不包含Wrapper,Wrapper是在具体请求的时候初始化的)和连接器(默认两种连接器Http,ajp)的启动,另外当然还做了一些配置文件的解析这个不多说。

    容器启动根据tomcat的生命周期启动方式是调用容器的start方法,start方法调用了具体的startInternal方法来做一些初始化的工作,其中就包括检测类文件变化的后台线程的初始化及启动,具体看一下ContainerBase的StartInternal方法:

在这个方法的最后一行,调用了threadStart()方法,这个方法就是在启动后台线程,看一下方法体:

由这段代码可知,这个方法启动了一条线程,其中ContainerBackgroundProcessor一定是实现了Runnable接口的具体的后台线程执行的逻辑,那就继续看:

至此就看到了后台线程的定义的真实面目,其中有个变量backgroundProcessDelay 这个变量的值会影响这条线程的睡眠时间,那也就说后台线程定时执行的时间是可配置的。最后一行调用了processChildren方法,这个方法又是具体的执行逻辑,那么断点调试看下是如何完成了类的重载的。

ProcessChildren方法定义如下:

这里调用了容器的backgroundProcess方法。Debug信息如下:

这个方法调用了载入器的WebappLoader的backgroundProcess方法。

标注处有两个校验项,一个是reloadable一个是modified方法。这个reloadable就是是否执行热部署的开关,这个可以在$CATALINA_HOME/conf/context.xml 当中配置一下,这个开关默认是不打开的。我修改了一下配置项如下:

Context.xml:

添加reloadable=true后,即可完成context容器的类的热部署。修改之后调试信息如下:

再来看一下第二个校验方法modified方法。这个modified方法会调用WebappClassLoader的Modified来判断文件是否被修改。如果两个校验项都为真的话,就会调用容器的reload方法(这里说的容器是Context容器)

 Context容器的这个reload方法定义如下:

这个reload方法实现的还是很简单粗暴的,就是讲整个Context容器重启了一下,先stop,然后再start.(容器都重启了,那容器课件范围的类自然会被重新加载了)

       以上就是tomcat7.x实现WEB-INF/classes当中类热部署的大体流程。除了WEB-INF/classes当中的类之外,还有一种特殊的类是默认热部署的,这个就是JSP。

       (2)为了实现JSP的加载部署,tomcat实现了另一个加载器即org.apache.jasper.servlet.JasperLoader.JSP属于一次消费品,每次访问都会重新加载(网上说的,这个源代码下次再研究下,在这先记录下)

       (3)在读源码的时候身边研究了下$CATALINA_HOME/conf/web.xml,这个配置文件是tomcat内置的配置文件,主要配置了两个Servlet. 具体的配置如下:

DefaultServlet是要作用是为静态资源请求提供服务,包括图片、html等。还有一个用来解析JSP的servlet:

JspServlet完成了Servlet的编译,以及请求的处理。下面那个配置项<load-on-startup>的意思是当配置项的数值大于0时(数值越大被加载的优先级越低)就在容器启动时候就加载这个Servlet 执行这个Servlet的init方法。


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!