Tomcat架构设计-组件生命周期

1 Tomcat中的组件

Tomcat里面有各种各样的组件,每个组件各司其职,组件之间又相互协作共同完成web服务器这样的工程。

image

组件关系

如果你仔细分析过这些组件,可以发现它们具有两层关系。

  • 第一层关系是组件有大有小,大组件管理小组件,比如 Server 管理 Service,Service 又管理连接器(Connector)和容器(Engline)。

  • 第二层关系是组件有外有内,外层组件控制内层组件,比如连接器(Connector)是外层组件,负责对外交流,外层组件调用容器(Engline)组件完成业务功能。也就是说,请求的处理过程是由外层组件来驱动的

2 Lifecycle 接口

2.1 Lifecycle设计原则

如果想让一个系统中组件能够对外提供服务,我们需要在服务启动时,为每个组进行创建,初始化,启动。同时在服务停止的时候,我们还需要每个组件在停止前释放资源,销毁这些组件。也就是说,Tomcat 需要动态地管理这些组件的生命周期

所谓设计就是要找到系统的变化点和不变点。这里的不变点就是每个组件都要经历创建、初始化、启动这几个过程,这些状态以及状态的转化是不变的。而变化点是每个具体组件具体的实现。

因此,我们把不变点抽象出来成为一个接口,这个接口跟生命周期有关,叫作 Lifecycle。Lifecycle接口里应该定义这么几个方法:init、start、stop 和 destroy,每个具体的组件去实现这些方法。

2.2 Lifecycle接口
public interface Lifecycle {
    ....
    // 初始化方法
    public void init() throws LifecycleException;
    // 启动方法
    public void start() throws LifecycleException;
    // 停止方法,和start对应
    public void stop() throws LifecycleException;
    // 销毁方法,和init对应
    public void destroy() throws LifecycleException;
    // 获取生命周期状态
    public LifecycleState getState();
    // 获取字符串类型的生命周期状态
    public String getStateName();
}
2.3 Lifecycle实现一键启动

在这样的设计中,在父组件的 init 方法里需要创建子组件并调用子组件的 init 方法。同样,在父组件的 start 方法里也需要调用子组件的 start 方法。因此调用者可以无差别的调用各组件的 init 方法和 start 方法,这就是组合模式的使用,并且只要调用最顶层组件,也就是 Server 组件的 init 和 start 方法,整个 Tomcat 就被启动起来了

3 Lifecycle 事件监听机制

3.1 事件监听机制

因为各个组件 init 和 start 方法的具体实现是复杂多变的。比如在 Host 容器的启动方法里需要扫描 webapps 目录下的 Web 应用,创建相应的 Context 容器,如果将来需要增加新的逻辑,直接修改 start 方法?这样会违反开闭原则,那如何解决这个问题呢?开闭原则说的是为了扩展系统的功能,你不能直接修改系统中已有的类,但是你可以定义新的类,这样可以大大降低系统修改的风险。

Lifecycle通过引入事件监听机制,一个组件函数业务处理可以通过添加监听器的方式实现对组件业务安全的动态扩展。

3.2 实现原理

那么这里我们把组件的生命周期定义成一个个状态,把状态的转变看作是一个事件。

public enum LifecycleState {
    //实例化完成时的状态
    NEW(false, null),
    // 容器正在初始化的状态,在INITIALIZED之前
    INITIALIZING(false, Lifecycle.BEFORE_INIT_EVENT),
    // 初始化完成的状态
    INITIALIZED(false, Lifecycle.AFTER_INIT_EVENT),
    // 启动前
    STARTING_PREP(false, Lifecycle.BEFORE_START_EVENT),
    // 启动过程中的状态
    STARTING(true, Lifecycle.START_EVENT),
    // 启动完成
    STARTED(true, Lifecycle.AFTER_START_EVENT),
    // 停止前的状态
    STOPPING_PREP(true, Lifecycle.BEFORE_STOP_EVENT),
    // 停止过程中
    STOPPING(false, Lifecycle.STOP_EVENT),
    // 停止完成
    STOPPED(false, Lifecycle.AFTER_STOP_EVENT),
    // 销毁中
    DESTROYING(false, Lifecycle.BEFORE_DESTROY_EVENT),
    // 完成销毁
    DESTROYED(false, Lifecycle.AFTER_DESTROY_EVENT),
    // 启动、停止过程中出现异常
    FAILED(false, null);

    /**
     * 组件当前是否正在运行
     */
    private final boolean available;


    /**
     * 组件当前状态触发的事件
     */
    private final String lifecycleEvent;

    private LifecycleState(boolean available, String lifecycleEvent) {
        this.available = available;
        this.lifecycleEvent = lifecycleEvent;
    }

    /**
     * 判断组件是否正在运行
     */
    public boolean isAvailable() {
        return available;
    }

    /**
     * 返回组件当前状态需要触发的事件
     */
    public String getLifecycleEvent() {
        return lifecycleEvent;
    }
}

事件是有监听器的,每个组件都内部都可以维护管理一组监听器,在事件触发后监听器里可以实现一些逻辑。

public interface Lifecycle {
    // 添加监听器
    public void addLifecycleListener(LifecycleListener listener);
    // 获取所以监听器
    public LifecycleListener[] findLifecycleListeners();
    // 移除某个监听器
    public void removeLifecycleListener(LifecycleListener listener);
    ...
}

[图片上传失败...(image-747a5d-1565247652167)]

3 LifecycleBase基类

有了接口,我们就要用类去实现接口。一般来说实现类不止一个,不同的类在实现接口时往往会有一些相同的逻辑,如果让各个子类都去实现一遍,就会有重复代码。那子类如何重用这部分逻辑呢?其实就是定义一个基类来实现共同的逻辑,然后让各个子类去继承它,就达到了重用的目的。

Tomcat 定义一个基类LifecycleBase 来实现 Lifecycle 接口,把一些公共的逻辑放到基类中去,比如生命状态的转变与维护、生命事件的触发以及监听器的添加和删除等,而子类就负责实现自己的初始化、启动和停止等方法。为了避免跟基类中的方法同名,我们把具体子类的实现方法改个名字,在后面加上 Internal,叫 initInternal、startInternal 等。

image

从图上可以看到,LifecycleBase 实现了 Lifecycle 接口中所有的方法,还定义了相应的抽象方法交给具体子类去实现,这是典型的模板设计模式

3.1 监听器管理的实现
/**
 * 管理当前组件生命周期监听器列表
 */
private final List<LifecycleListener> lifecycleListeners = new CopyOnWriteArrayList<>();

/**
 * 给当前组件添加一个生命周期监听器
 */
@Override
public void addLifecycleListener(LifecycleListener listener) {
    lifecycleListeners.add(listener);
}

/**
 * 获取当前组件所有生命周期监听器
 */
@Override
public LifecycleListener[] findLifecycleListeners() {
    return lifecycleListeners.toArray(new LifecycleListener[0]);
}

/**
 * 移除当前组件一个生命周期监听器
 */
@Override
public void removeLifecycleListener(LifecycleListener listener) {
    lifecycleListeners.remove(listener);
}

3.2 事件的触发
/**
 * 触发一个生命周期事件,通知所有生命周期监听器触发
 *
 * @param type  Event type
 * @param data  Data associated with event.
 */
protected void fireLifecycleEvent(String type, Object data) {
    LifecycleEvent event = new LifecycleEvent(this, type, data);
    for (LifecycleListener listener : lifecycleListeners) {
        listener.lifecycleEvent(event);
    }
}
3.3 生命状态的转变与维护(状态机)
3.1.1 组件初始化
/**
 *  组件初始化动作,所有组件通用操作
 *   1 检查校验当前组件状态是否能够初始化
 *   2 修改当前的状态从 NEW-->INITIALIZING
 *   3 调用每个组件模板方法实现完成初始化动作
 *   4 修改当前的状态从 INITIALIZING-->INITIALIZED
 */
@Override
public final synchronized void init() throws LifecycleException {
    /** 非NEW状态,不允许调用init()方法 **/
    if (!state.equals(LifecycleState.NEW)) {
        /** 从sm获取"lifecycleBase.invalidTransition"属性对应日志格式,抛出LifecycleException异常 **/
        invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
    }

    try {
        /** 初始化逻辑之前,将状态变更为`INITIALIZING` **/
        setStateInternal(LifecycleState.INITIALIZING, null, false);
        /** 初始化组件,该方法为一个abstract模板方法,需要组件自行实现  **/
        initInternal();
        /** 初始化完成之后,状态变更为`INITIALIZED`  **/
        setStateInternal(LifecycleState.INITIALIZED, null, false);
    }
    /** 初始化的过程中,可能会有异常抛出,这时需要捕获异常,并将状态变更为`FAILED` **/
    catch (Throwable t) {
        ExceptionUtils.handleThrowable(t);
        setStateInternal(LifecycleState.FAILED, null, false);
        throw new LifecycleException(
                sm.getString("lifecycleBase.initFail",toString()), t);
    }
}

/**
 * 初始化模板方法
 */
protected abstract void initInternal() throws LifecycleException;
3.1.2 组件启动
/**
 * 组件启动动作,所有组件通用操作
 */
@Override
public final synchronized void start() throws LifecycleException {
    /** 组件当前状态为`STARTING_PREP`、`STARTING`和`STARTED时,将忽略start()逻辑 **/
    if (LifecycleState.STARTING_PREP.equals(state) || LifecycleState.STARTING.equals(state) ||
            LifecycleState.STARTED.equals(state)) {

        if (log.isDebugEnabled()) {
            Exception e = new LifecycleException();
            log.debug(sm.getString("lifecycleBase.alreadyStarted", toString()), e);
        } else if (log.isInfoEnabled()) {
            log.info(sm.getString("lifecycleBase.alreadyStarted", toString()));
        }

        return;
    }
    /** 组件当前状态为`NEW`时,先执行init()方法 **/
    if (state.equals(LifecycleState.NEW)) {
        init();
    }
    /** 组件当前状态为`FAILED`时,执行stop()方法 **/
    else if (state.equals(LifecycleState.FAILED)) {
        stop();
    }
    /** 组件当前状态不是`INITIALIZED`和`STOPPED`时,则说明是非法的操作,抛出异常**/
    else if (!state.equals(LifecycleState.INITIALIZED) &&
            !state.equals(LifecycleState.STOPPED)) {
        /** 从sm获取"lifecycleBase.invalidTransition"属性对应日志格式,抛出LifecycleException异常 **/
        invalidTransition(Lifecycle.BEFORE_START_EVENT);
    }

    try {
        /** 启动逻辑之前,先将状态变更为`STARTING_PREP` **/
        setStateInternal(LifecycleState.STARTING_PREP, null, false);
        /** 启动组件,该方法为一个abstract模板方法,需要组件自行实现   **/
        startInternal();
        /** 如果启动组件发生异常状态被更新为'FAILED',调用stop() **/
        if (state.equals(LifecycleState.FAILED)) {
            // This is a 'controlled' failure. The component put itself into the
            // FAILED state so call stop() to complete the clean-up.
            stop();
        }
        /** 如果启动组件后状态未被更新为STARTING,抛出异常 **/
        else if (!state.equals(LifecycleState.STARTING)) {
            /** 从sm获取"lifecycleBase.invalidTransition"属性对应日志格式,抛出LifecycleException异常 **/
            invalidTransition(Lifecycle.AFTER_START_EVENT);
        }
        /** 启动完成,将状态变更为`STARTED` **/
        else {
            setStateInternal(LifecycleState.STARTED, null, false);
        }
    }
    /** 初始化的过程中,可能会有异常抛出,这时需要捕获异常,并将状态变更为`FAILED` **/
    catch (Throwable t) {
        ExceptionUtils.handleThrowable(t);
        setStateInternal(LifecycleState.FAILED, null, false);
        throw new LifecycleException(sm.getString("lifecycleBase.startFail", toString()), t);
    }
}

/**
 * 启动模板方法
 */
protected abstract void startInternal() throws LifecycleException;
3.1.3 组件停止
/**
 * 组件停止化动作,所有组件通用操作
 */
@Override
public final synchronized void stop() throws LifecycleException {
    /** 组件状态为`STOPPING_PREP`、`STOPPING`和`STOPPED'时,将忽略start()逻辑 **/
    if (LifecycleState.STOPPING_PREP.equals(state) || LifecycleState.STOPPING.equals(state) ||
            LifecycleState.STOPPED.equals(state)) {

        if (log.isDebugEnabled()) {
            Exception e = new LifecycleException();
            log.debug(sm.getString("lifecycleBase.alreadyStopped", toString()), e);
        } else if (log.isInfoEnabled()) {
            log.info(sm.getString("lifecycleBase.alreadyStopped", toString()));
        }

        return;
    }

    /** 组件当前状态`NEW`时,直接将状态变更为`STOPPED`  **/
    if (state.equals(LifecycleState.NEW)) {
        state = LifecycleState.STOPPED;
        return;
    }

    /** 组件当前状态不是`STARTED`和`FAILED`时,则说明是非法的操作,抛出异常**/
    if (!state.equals(LifecycleState.STARTED) && !state.equals(LifecycleState.FAILED)) {
        /** 从sm获取"lifecycleBase.invalidTransition"属性对应日志格式,抛出LifecycleException异常 **/
        invalidTransition(Lifecycle.BEFORE_STOP_EVENT);
    }

    try {
        /** 组件当前状态为`FAILED`时,直接触发BEFORE_STOP_EVENT事件 **/
        if (state.equals(LifecycleState.FAILED)) {
            fireLifecycleEvent(BEFORE_STOP_EVENT, null);
        } else {
            /** 停止逻辑之前,先将状态变更为`STOPPING_PREP` **/
            setStateInternal(LifecycleState.STOPPING_PREP, null, false);
        }

        /** 停止组件,该方法为一个abstract模板方法,需要组件自行实现   **/
        stopInternal();

        /** 停止组件后,当前状态不是`STOPPING`,`FAILED`抛出异常 **/
        if (!state.equals(LifecycleState.STOPPING) && !state.equals(LifecycleState.FAILED)) {
            /** 从sm获取"lifecycleBase.invalidTransition"属性对应日志格式,抛出LifecycleException异常 **/
            invalidTransition(Lifecycle.AFTER_STOP_EVENT);
        }

        /** 停止完成,将状态变更为`STOPPED` **/
        setStateInternal(LifecycleState.STOPPED, null, false);
    }
    /** 初始化的过程中,可能会有异常抛出,这时需要捕获异常,并将状态变更为`FAILED` **/
    catch (Throwable t) {
        ExceptionUtils.handleThrowable(t);
        setStateInternal(LifecycleState.FAILED, null, false);
        throw new LifecycleException(sm.getString("lifecycleBase.stopFail",toString()), t);
    } finally {
        /** 当前组件是SingleUse子类设置状态为'STOPPED'  **/
        if (this instanceof Lifecycle.SingleUse) {
            // Complete stop process first
            setStateInternal(LifecycleState.STOPPED, null, false);
            destroy();
        }
    }
}

/**
 * 停止模板方法
 */
protected abstract void stopInternal() throws LifecycleException;    
3.1.4 组件的销毁
/**
 * 组件销毁动作,所有组件通用操作
 */
@Override
public final synchronized void destroy() throws LifecycleException {
    /** 组件当前状态为`FAILED`状态时,直接触发stop()逻辑 **/
    if (LifecycleState.FAILED.equals(state)) {
        try {
            // Triggers clean-up
            stop();
        } catch (LifecycleException e) {
            // Just log. Still want to destroy.
            log.warn(sm.getString(
                    "lifecycleBase.destroyStopFail", toString()), e);
        }
    }

    /** 当前状态为 `DESTROYING`和`DESTROYED`时,忽略destroy的执行 **/
    if (LifecycleState.DESTROYING.equals(state) ||
            LifecycleState.DESTROYED.equals(state)) {

        if (log.isDebugEnabled()) {
            Exception e = new LifecycleException();
            log.debug(sm.getString("lifecycleBase.alreadyDestroyed", toString()), e);
        } else if (log.isInfoEnabled() && !(this instanceof Lifecycle.SingleUse)) {
            // Rather than have every component that might need to call
            // destroy() check for SingleUse, don't log an info message if
            // multiple calls are made to destroy()
            log.info(sm.getString("lifecycleBase.alreadyDestroyed", toString()));
        }

        return;
    }

    /** 非法状态判断,抛出异常 **/
    if (!state.equals(LifecycleState.STOPPED) &&
            !state.equals(LifecycleState.FAILED) &&
            !state.equals(LifecycleState.NEW) &&
            !state.equals(LifecycleState.INITIALIZED)) {
        /** 从sm获取"lifecycleBase.invalidTransition"属性对应日志格式,抛出LifecycleException异常 **/
        invalidTransition(Lifecycle.BEFORE_DESTROY_EVENT);
    }

    try {
        /** 销毁逻辑之前,将状态变更为`DESTROYING` **/
        setStateInternal(LifecycleState.DESTROYING, null, false);
        /** 停止组件,该方法为一个abstract模板方法,需要组件自行实现   **/
        destroyInternal();
        /** 销毁完成,将状态变更为`DESTROYED` **/
        setStateInternal(LifecycleState.DESTROYED, null, false);
    } catch (Throwable t) {
        ExceptionUtils.handleThrowable(t);
        setStateInternal(LifecycleState.FAILED, null, false);
        throw new LifecycleException(
                sm.getString("lifecycleBase.destroyFail",toString()), t);
    }
}


protected abstract void destroyInternal() throws LifecycleException;
3.4 其他方法
 /**
     * 获取当前组件状态
     */
    @Override
    public LifecycleState getState() {
        return state;
    }


    /**
     * 获取当前组件状态名称
     */
    @Override
    public String getStateName() {
        return getState().toString();
    }


    /**
     * 更新当前组件的状态
     */
    protected synchronized void setState(LifecycleState state)
            throws LifecycleException {
        setStateInternal(state, null, true);
    }


    /**
     * 更新当前组件的状态
     */
    protected synchronized void setState(LifecycleState state, Object data)
            throws LifecycleException {
        setStateInternal(state, data, true);
    }

    /**
     * 更新当前组件的状态
     * @param state  更新的状态
     * @param data   触发事件数据
     * @param check  是否对组件状态更新做检查
     * @throws LifecycleException
     */
    private synchronized void setStateInternal(LifecycleState state,
            Object data, boolean check) throws LifecycleException {

        if (log.isDebugEnabled()) {
            log.debug(sm.getString("lifecycleBase.setState", this, state));
        }

        if (check) {

            /** 检查当前状态是否为nul **/
            if (state == null) {
                /** 从sm获取当前日志格式,抛出LifecycleException异常 **/
                invalidTransition("null");
                return;
            }

            /** 检查状态变更逻辑是否错误 **/
            if (!(state == LifecycleState.FAILED ||
                    (this.state == LifecycleState.STARTING_PREP &&
                            state == LifecycleState.STARTING) ||
                    (this.state == LifecycleState.STOPPING_PREP &&
                            state == LifecycleState.STOPPING) ||
                    (this.state == LifecycleState.FAILED &&
                            state == LifecycleState.STOPPING))) {
                /** 从sm获取当前日志格式,抛出LifecycleException异常 **/
                invalidTransition(state.name());
            }
        }

        /** 更新当前组件状态 **/
        this.state = state;
        String lifecycleEvent = state.getLifecycleEvent();
        /** 获取更新状态需要触发的事件 **/
        if (lifecycleEvent != null) {
            fireLifecycleEvent(lifecycleEvent, data);
        }
    }
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,907评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,987评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,298评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,586评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,633评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,488评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,275评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,176评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,619评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,819评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,932评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,655评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,265评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,871评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,994评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,095评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,884评论 2 354

推荐阅读更多精彩内容