tomcat 源码分析(三)基于JMX的生命周期管理

根据tomcat中server.xml文件解析出来的各个对象比如:Server、Service、Connector等。这些容器都具有新建、初始化完成、启动、停止、失败、销毁等状态。tomcat的实现提供了对这些容器的生命周期管理,深入剖析这一过程

生命周期类接口设计类图如下:


tomcat 源码分析(三)基于JMX的生命周期管理_第1张图片

涉及到的类的简单介绍:

Lifecycle:定义了容器生命周期、容器状态转换及容器状态迁移事件的监听器注册和移除等主要接口;

LifecycleBase:作为Lifecycle接口的抽象实现类,运用抽象模板模式将所有容器的生命周期及状态转换衔接起来,此外还提供了生成LifecycleEvent事件的接口;

LifecycleSupport:提供有关LifecycleEvent事件的监听器注册、移除,并且使用经典的监听器模式,实现事件生成后触打监听器的实现;

MBeanRegistration:JmxEnabled 的父类, jmx框架提供的注册MBean的接口,引入此接口是为了便于使用JMX提供的管理功能;

LifecycleMBeanBase:Tomcat提供的对MBeanRegistration的抽象实现类,运用抽象模板模式将所有容器统一注册到JMX;

ContainerBase、StandardServer、StandardService、WebappLoader、Connector、StandardContext、StandardEngine、StandardHost、StandardWrapper等容器都继承了LifecycleMBeanBase,因此这些容器都具有了同样的生命周期并可以通过JMX进行管理。

Tomcat 容器的组成:

StandardServer、StandardService、Connector、StandardContext这些容器,彼此之间都有父子关系,每个容器都可能包含零个或者多个子容器如下:

tomcat 源码分析(三)基于JMX的生命周期管理_第2张图片

Tomcat 容器状态:

NEW:容器刚刚创建时,即在LifecycleBase实例构造完成时的状态。

INITIALIZED:容器初始化完成时的状态。

STARTING_PREP:容器启动前的状态。

STARTING:容器启动过程中的状态。

STARTED:容器启动完成的状态。

STOPPING_PREP:容器停止前的状态。

STOPPING:容器停止过程中的状态。

STOPPED:容器停止完成的状态。

DESTROYED:容器销毁后的状态。

FAILED:容器启动、停止过程中出现异常的状态。

MUST_STOP:此状态未使用。

MUST_DESTROY:此状态未使用。

这些状态都定义在枚举类LifecycleState中。

事件与监听

每个容器由于继承自LifecycleBase,当容器状态发生变化时,都会调用fireLifecycleEvent方法,生成LifecycleEvent,并且交由此容器的事件监听器处理。LifecycleBase的fireLifecycleEvent方法的实现见代码一:

tomcat 源码分析(三)基于JMX的生命周期管理_第3张图片

LifecycleSupport的实现如下见代码二:

tomcat 源码分析(三)基于JMX的生命周期管理_第4张图片

将事件通知给所有监听当前容器的生命周期监听器LifecycleListener,并调用LifecycleListener的lifecycleEvent方法。每个容器都维护这一个监听器缓存,其实现如下见代码三:

tomcat 源码分析(三)基于JMX的生命周期管理_第5张图片

每个容器在新建、初始化、启动,销毁,被添加到父容器的过程中都会调用父类LifecycleBase的addLifecycleListener方法,addLifecycleListener的实现见代码如见代码四:

tomcat 源码分析(三)基于JMX的生命周期管理_第6张图片

LifecycleBase的addLifecycleListener方法实际是对LifecycleSupport的addLifecycleListener方法的简单代理,LifecycleSupport的addLifecycleListener方法的实现,见代码五:

tomcat 源码分析(三)基于JMX的生命周期管理_第7张图片

在代码清单2中,我们讲过容器会最终调用每个对此容器感兴趣的LifecycleListener的lifecycleEvent方法,那么LifecycleListener的lifecycleEvent方法会做些什么呢?为了简单起见,我们以监听器AprLifecycleListener为例,AprLifecycleListener的lifecycleEvent方法的实现,见代码六:

tomcat 源码分析(三)基于JMX的生命周期管理_第8张图片

容器生命周期

每个容器都会有自身的生命周期,其中也涉及状态的迁移,以及伴随的事件生成,本节详细介绍Tomcat中的容器生命周期实现。所有容器的转态转换(如新疆、初始化、启动、停止等)都是由外到内,由上到下进行,即先执行父容器的状态转换及相关操作,然后再执行子容器的转态转换,这个过程是层层迭代执行的。

容器新建

所有容器在构造的过程中,都会首先对父类LifecycleBase进行构造。LifecycleBase中定义了所有容器的起始状态为LifecycleState.NEW;

tomcat 源码分析(三)基于JMX的生命周期管理_第9张图片
容器的初始化过程

所说的具体容器,实际就是LifecycleBase的具体实现类,目前LifecycleBase的类继承体系;

tomcat 源码分析(三)基于JMX的生命周期管理_第10张图片
LifecycleBase的类继承体系

我们对Tomcat的源码进行分析,其处理步骤如下:

调用方调用容器父类LifecycleBase的init方法,LifecycleBase的init方法主要完成一些所有容器公共抽象出来的动作;

LifecycleBase的init方法调用具体容器的initInternal方法实现,此initInternal方法用于对容器本身真正的初始化;

具体容器的initInternal方法调用父类LifecycleMBeanBase的initInternal方法实现,此initInternal方法用于将容器托管到JMX,便于运维管理;

LifecycleMBeanBase的initInternal方法调用自身的register方法,将容器作为MBean注册到MBeanServer;

容器如果有子容器,会调用子容器的init方法;

容器初始化完毕,LifecycleBase会将容器的状态更改为初始化完毕,即LifecycleState.INITIALIZED。

对容器初始化LifecycleBase的源码进行分析,init方法的实现:

tomcat 源码分析(三)基于JMX的生命周期管理_第11张图片

只有当前容器的状态处于LifecycleState.NEW的才可以被初始化,真正执行初始化的方法是initInternal,当初始化完毕,当前容器的状态会被更改为LifecycleState.INITIALIZED。为了简便起见,我们还是以StandardServer这个容器为例,StandardServer的initInternal方法的实现;

步骤一  将当前容器注册到JMX

StandServer调用直接父类LifecycleMBeanBase的initInternal方法,为当前容器创建DynamicMBean,并注册到JMX中。

tomcat 源码分析(三)基于JMX的生命周期管理_第12张图片

LifecycleMBeanBase的register方法会为当前容器创建对应的注册名称,以StandardServer为例,getDomain默认返回Catalina,因此StandardServer的JMX注册名称默认为Catalina:type=Server,真正的注册在registerComponent方法中实现;

tomcat 源码分析(三)基于JMX的生命周期管理_第13张图片

Registry的registerComponent方法会为当前容器(如StandardServer)创建DynamicMBean,并且注册到MBeanServer;

tomcat 源码分析(三)基于JMX的生命周期管理_第14张图片

步骤二将StringCache、MBeanFactory、globalNamingResources注册到JMX;其中StringCache的注册名为Catalina:type=StringCache,MBeanFactory的注册名为Catalina:type=MBeanFactory,globalNamingResources的注册名为Catalina:type=NamingResources。

步骤三初始化子容器

从代码中看到StandardServer主要对Service子容器进行初始化,默认是StandardService。

注意:个别容器并不完全遵循以上的初始化过程,比如ProtocolHandler作为Connector的子容器,其初始化过程并不是由Connector的initInternal方法调用的,而是与启动过程一道被Connector的startInternal方法所调用。

容器启动

每个容器的start方法是自身启动的入口,其启动过程对Tomcat的源码进行分析,其处理步骤如下:

调用方调用容器父类LifecycleBase的start方法,LifecycleBase的start方法主要完成一些所有容器公共抽象出来的动作;

LifecycleBase的start方法先将容器状态改为LifecycleState.STARTING_PREP,然后调用具体容器的startInternal方法实现,此startInternal方法用于对容器本身真正的初始化;

具体容器的startInternal方法会将容器状态改为LifecycleState.STARTING,容器如果有子容器,会调用子容器的start方法启动子容器;

容器启动完毕,LifecycleBase会将容器的状态更改为启动完毕,即LifecycleState.STARTED。

除了初始化、启动外,各个容器还有停止和销毁的生命周期,其原理与初始化、启动类似有兴趣的读者可以自行研究

你可能感兴趣的:(tomcat 源码分析(三)基于JMX的生命周期管理)