Tomcat 热部署实现方式源码分析总结
2014-04-17 16:37
260 查看
研究了一下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方法:
![](http://ugc.qpic.cn/adapt/0/bbc41ec9-67b2-6ae9-656d-887fe7b0f112/0)
在这个方法的最后一行,调用了threadStart()方法,这个方法就是在启动后台线程,看一下方法体:
![](http://ugc.qpic.cn/adapt/0/c3286386-c634-c775-01fe-d12a2b46f327/0)
由这段代码可知,这个方法启动了一条线程,其中ContainerBackgroundProcessor一定是实现了Runnable接口的具体的后台线程执行的逻辑,那就继续看:
![](http://ugc.qpic.cn/adapt/0/a4dbd181-93b9-57ed-54b1-a9a39e9dccfe/0)
至此就看到了后台线程的定义的真实面目,其中有个变量backgroundProcessDelay 这个变量的值会影响这条线程的睡眠时间,那也就说后台线程定时执行的时间是可配置的。最后一行调用了processChildren方法,这个方法又是具体的执行逻辑,那么断点调试看下是如何完成了类的重载的。
ProcessChildren方法定义如下:
![](http://ugc.qpic.cn/adapt/0/e0dfbe5a-2ec5-40a9-a76c-acd23ee5863f/0)
这里调用了容器的backgroundProcess方法。Debug信息如下:
![](http://ugc.qpic.cn/adapt/0/b418f409-6e6a-c8ca-cfc4-792b8676487b/0)
这个方法调用了载入器的WebappLoader的backgroundProcess方法。
WebappLoader的backgroundProcess方法如下:
![](http://ugc.qpic.cn/adapt/0/77665130-61c3-f82e-50ae-65554e39d680/0)
标注处有两个校验项,一个是reloadable一个是modified方法。这个reloadable就是是否执行热部署的开关,这个可以在$CATALINA_HOME/conf/context.xml 当中配置一下,这个开关默认是不打开的。我修改了一下配置项如下:
Context.xml:
![](http://ugc.qpic.cn/adapt/0/e66ec843-1890-7ea5-441c-ed4a566e8a16/0)
添加reloadable=true后,即可完成context容器的类的热部署。修改之后调试信息如下:
![](http://ugc.qpic.cn/adapt/0/d36a7ab3-ef8e-12f1-a70d-3d82ff75fed0/0)
再来看一下第二个校验方法modified方法。这个modified方法会调用WebappClassLoader的Modified来判断文件是否被修改。如果两个校验项都为真的话,就会调用容器的reload方法(这里说的容器是Context容器)
Context容器的这个reload方法定义如下:
![](http://ugc.qpic.cn/adapt/0/a4fbdca8-f241-7ab7-32e5-d5724b0b7a75/0)
这个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. 具体的配置如下:
![](http://ugc.qpic.cn/adapt/0/c00bfb26-048c-f1cd-2d8f-6536172e0fea/0)
DefaultServlet是要作用是为静态资源请求提供服务,包括图片、html等。还有一个用来解析JSP的servlet:
![](http://ugc.qpic.cn/adapt/0/2867e5ed-5eff-2113-bbbb-dd9b834fd824/0)
JspServlet完成了Servlet的编译,以及请求的处理。下面那个配置项<load-on-startup>的意思是当配置项的数值大于0时(数值越大被加载的优先级越低)就在容器启动时候就加载这个Servlet 执行这个Servlet的init方法。
(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方法。
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方法。
相关文章推荐
- Tomcat 热部署实现方式源码分析总结
- Tomcat 热部署实现方式源码分析总结
- Tomcat 热部署实现方式源码分析总结
- 结合Android源码分析总结单例模式的几种实现方式
- Tomcat源码分析(十)--部署器
- Tomcat源码分析(十)--部署器
- 配置tomcat5.5 jndi 各种配置方式 分析总结(mysql)
- tomcat 上部署项目方式总结
- tomcat源码分析(一)初始化---Debug方式
- tomcat源码分析(二)启动---Debug方式
- Tomcat源码分析之—组件启动实现分析
- tomcat5_5 jndi各种配置方式分析总结(mysql)
- Tomcat源码分析之Server与Lifecycle的设计与实现
- Apache Spark源码走读之7 -- Standalone部署方式分析
- Tomcat源码分析(十)--部署器 转载
- Mangos源码分析(10):服务器公共组件实现之发包的方式
- Tomcat源码分析 之 Tomcat如何监测部署应用的改变并进行重新部署
- JDK源码分析之concurrent包(三) -- Future方式的实现
- Tomcat实现:Servlet与web.xml介绍 以及 源码分析Tomcat实现细节
- Quartz源码分析(一)------ 以线程等待的方式实现按时间调度