tomcat源码解析(四)——tomcat基本结构简述

来源:互联网 发布:ps是什么网络用语 编辑:程序博客网 时间:2024/05/16 17:31

关于tomcat结构,其生命周期管理方式为自上而下;在tomcat6中,每一个关键组件都实现了Lifecycle接口;而在tomcat9中,每个组件都继承了LifecycleMBeanBase类,而LifecycleMBeanBase类继承了LifecycleBase类,在LifecycleBase中实现了Lifecycle接口;所以Lifecycle是管理各个重要组件生命周期的关键;

本文将以tomcat-9.0.0.M9的源码为基础;在对具体生命周期说明之前,需要了解其基本组件的结构;


这里图中只包括了最主要的几个部分,这几个类也是tomcat中最基本的实现;

StandardServer:是tomcat状态管理的主要类,通过它管理下面多个service服务,即一个tomcat管理多个web工程;

StandardService:每个web工程对应一个StandardService;

StandardThreadExecutor:线程池;

Connector:网络接口模块;

StandardEngine:执行类;

StandardHost:一般负责管理域名部分;

StandardContext:负责管理context部分;

StandardWrapper:映射具体的URL资源;

对以上各个模块认知深度还不够,但具体的理解可以分而治之,逐个部分去进行了解。


以上各组件实际上是与server.xml相互对应的,一般通过简单的配置xml就可以修改各组件的配置。

通过我对tomcat9的server.xml解析部分的源码解读;反推出了一个较为完整的文件的节点配置结构:


这上面只有节点的名称,对应的xml中配置的节点;图中的父节点指向子节点;每个节点的属性则需要在对各功能模块深入了解中,才能明白作用。

图中的server、service、engine、host、context、executor等,与基本组件相互对应。

从上图中,可以对tomcat的所有功能模块有大概的认知。从中可以发现一些较为核心的节点;例如GlobalNamingResources、Connector、Cluster、Context等,这些模块涉及功能较多,也是具体实现的关键。


接口Lifecycle中包含了对组件行为的约束,init、start、stop、destory等,以及内部的监听。

在tomcat9中,抽象程度比tomcat6更高,在版本6中各组件直接实现接口;在版本9中则由LifecycleBase抽象类实现,其中实现了对事件的监听,而将具体的事件业务逻辑交给子类实现,这样使得各组件更专注于业务功能。

以init的源码为例(其他的基本相同):

    @Override    public final synchronized void init() throws LifecycleException {        if (!state.equals(LifecycleState.NEW)) {            invalidTransition(Lifecycle.BEFORE_INIT_EVENT);        }        setStateInternal(LifecycleState.INITIALIZING, null, false);        try {            initInternal();        } catch (Throwable t) {            ExceptionUtils.handleThrowable(t);            setStateInternal(LifecycleState.FAILED, null, false);            throw new LifecycleException(                    sm.getString("lifecycleBase.initFail",toString()), t);        }        setStateInternal(LifecycleState.INITIALIZED, null, false);    }    protected abstract void initInternal() throws LifecycleException;
子类只需要覆盖initInternal()方法,而且只关心自己所需要的初始化逻辑,事件监听逻辑在这里已经完成。


LifecycleMBeanBase类继承了LifecycleBase,里面实现了JmxEnabled接口;加入了对MBean的支持,自动注册各组件,实现JMX管理,以及对注册的事件管理;

ContainerBase类继承了LifecycleMBeanBase,添加了对容器具体功能的实现,其子类例如StandardEngine、StandardHost、StandardContext、StandardWrapper等。

tomcat9中重要的组件都会继承LifecycleMBeanBase类,例如StandardServer、StandardService、StandardEngine等。

在Catalina类的load方法中首先在解析server.xml时通过Digester类,将各组件初始化完成;

接下来在执行

getServer().init();

getServer().start();

等方法,实际对应的是StandardServer类的对象;通过操作StandardServer的对象,来完成对所有组件生命周期的管理;


以start为例,在LifecycleBase中已经实现start方法,组件只需实现startInternal()方法;

StandardServer源码如下:

    /**     * Start nested components ({@link Service}s) and implement the requirements     * of {@link org.apache.catalina.util.LifecycleBase#startInternal()}.     *     * @exception LifecycleException if this component detects a fatal error     *  that prevents this component from being used     */    @Override    protected void startInternal() throws LifecycleException {        fireLifecycleEvent(CONFIGURE_START_EVENT, null);        setState(LifecycleState.STARTING);        globalNamingResources.start();        // Start our defined Services        synchronized (servicesLock) {            for (int i = 0; i < services.length; i++) {                services[i].start();            }        }    }
这里实现自己全局属性初始化后调用了services[i].start();,以此实现自己管理的service;

这里对应的service是StandardService;同理可以查看StandardService类的startInternal()方法;

    /**     * Start nested components ({@link Executor}s, {@link Connector}s and     * {@link Container}s) and implement the requirements of     * {@link org.apache.catalina.util.LifecycleBase#startInternal()}.     *     * @exception LifecycleException if this component detects a fatal error     *  that prevents this component from being used     */    @Override    protected void startInternal() throws LifecycleException {        if(log.isInfoEnabled())            log.info(sm.getString("standardService.start.name", this.name));        setState(LifecycleState.STARTING);        // Start our defined Container first        if (engine != null) {            synchronized (engine) {                engine.start();            }        }        synchronized (executors) {            for (Executor executor: executors) {                executor.start();            }        }        mapperListener.start();        // Start our defined Connectors second        synchronized (connectorsLock) {            for (Connector connector: connectors) {                try {                    // If it has already failed, don't try and start it                    if (connector.getState() != LifecycleState.FAILED) {                        connector.start();                    }                } catch (Exception e) {                    log.error(sm.getString(                            "standardService.connector.startFailed",                            connector), e);                }            }        }    }
这里也是先实现自己管理各组件的启动,如最之前图中的描述的组件engine、executor、connector;

其中只拿engine为例,对应的是StandardEngine,继承自ContainerBase;

StandardEngine的startInternal()方法调用super.startInternal();即是调用ContainerBase的startInternal()方法;

ContainerBase的startInternal()源码如下:

    /**     * Start this component and implement the requirements     * of {@link org.apache.catalina.util.LifecycleBase#startInternal()}.     *     * @exception LifecycleException if this component detects a fatal error     *  that prevents this component from being used     */    @Override    protected synchronized void startInternal() throws LifecycleException {        // Start our subordinate components, if any        logger = null;        getLogger();        Cluster cluster = getClusterInternal();        if (cluster instanceof Lifecycle) {            ((Lifecycle) cluster).start();        }        Realm realm = getRealmInternal();        if (realm instanceof Lifecycle) {            ((Lifecycle) realm).start();        }        // Start our child containers, if any        Container children[] = findChildren();        List<Future<Void>> results = new ArrayList<>();        for (int i = 0; i < children.length; i++) {            results.add(startStopExecutor.submit(new StartChild(children[i])));        }        boolean fail = false;        for (Future<Void> result : results) {            try {                result.get();            } catch (Exception e) {                log.error(sm.getString("containerBase.threadedStartFailed"), e);                fail = true;            }        }        if (fail) {            throw new LifecycleException(                    sm.getString("containerBase.threadedStartFailed"));        }        // Start the Valves in our pipeline (including the basic), if any        if (pipeline instanceof Lifecycle)            ((Lifecycle) pipeline).start();        setState(LifecycleState.STARTING);        // Start our thread        threadStart();    }
这段代码也是对各个组件执行启动操作;
在这段代码中StandardEngine启动StandardHost则分为两步,先将StandardHost的对象加入列表,之后通过线程池启动;对应的代码如下:

</pre></p><p><pre name="code" class="java">
        // Start our child containers, if any        Container children[] = findChildren();        List<Future<Void>> results = new ArrayList<>();        for (int i = 0; i < children.length; i++) {            results.add(startStopExecutor.submit(new StartChild(children[i])));        }        boolean fail = false;        for (Future<Void> result : results) {            try {                result.get();            } catch (Exception e) {                log.error(sm.getString("containerBase.threadedStartFailed"), e);                fail = true;            }        }
在此之后的启动代码都是类似的,StandardHost管理StandardContext,StandardContext管理StandardWrapper;而每个组件除此之外还有管理自己的特有的模块组件;


剩下的可以依次类推,至此组件管理方面结束;接下来的源码解析就是对内部各个模块功能跟踪。


0 0