Tomcat-整体架构和Lifecycle


​ 基于Tomcat-8.5.x版本,简单分析了整体的架构和核心组件。并详细分析和总结了Lifecycle机制

核心组件和架构

Tomcat 的架构可以抽象为一棵树,核心组件结构如下:

  • 根节点是 Server,表示整个 Tomcat 实例(即一个 JVM 进程)
  • Server 下包含一个或多个 Service,代表一组 Web 服务
  • 每个 Service 包含:
    • 一个或多个 Connector,负责监听不同协议/端口的请求(如 HTTP、HTTPS)
    • 唯一的一个 Engine,与Service一对一的关系,用于处理由 Connector 接收到的请求
  • Engine 下包含多个 Host,每个 Host 对应一个虚拟主机(通过域名区分)
  • 每个 Host管理多个 Context,每个 Context 对应一个 Web 应用(即一个 war)
  • 每个 Context 下包含多个 Wrapper,每个 Wrapper 对应一个具体的 Servlet

tomcat-architecture.png

Lifecycle

Lifecycle 是 Tomcat 中最核心的接口之一。所有关键组件都实现了该接口,以便在生命周期事件(如init、start、stop等)到来时执行自身的职责,并将事件级联传递给子组件。因此,深入理解 Lifecycle 的作用和机制,是阅读和掌握 Tomcat 源码的基础。

public interface Lifecycle {

    // ======================== 生命周期事件常量 ========================

    String BEFORE_INIT_EVENT = "before_init";
    String AFTER_INIT_EVENT = "after_init";

    String BEFORE_START_EVENT = "before_start";
    String START_EVENT = "start";
    String AFTER_START_EVENT = "after_start";

    String BEFORE_STOP_EVENT = "before_stop";
    String STOP_EVENT = "stop";
    String AFTER_STOP_EVENT = "after_stop";

    String BEFORE_DESTROY_EVENT = "before_destroy";
    String AFTER_DESTROY_EVENT = "after_destroy";

    /** 周期性事件(如后台定时任务触发) */
    String PERIODIC_EVENT = "periodic";

    /** 配置启动事件(内部扩展使用) */
    String CONFIGURE_START_EVENT = "configure_start";
    /** 配置停止事件(内部扩展使用) */
    String CONFIGURE_STOP_EVENT = "configure_stop";

    // ======================== 生命周期监听器相关方法 ========================

    void addLifecycleListener(LifecycleListener listener);

    LifecycleListener[] findLifecycleListeners();

    void removeLifecycleListener(LifecycleListener listener);

    // ======================== 生命周期控制方法 ========================

    /**
     * 初始化组件。组件只能初始化一次,且必须在启动前完成。
     */
    void init() throws LifecycleException;

    /**
     * 启动组件。如果未初始化,会隐式调用 init()
     */
    void start() throws LifecycleException;

    /**
     * 停止组件。可在调用 start() 后再次调用以恢复运行
     */
    void stop() throws LifecycleException;

    /**
     * 销毁组件,释放资源。此操作不可逆。
     */
    void destroy() throws LifecycleException;

    LifecycleState getState();

    String getStateName();

    /**
     * 标记接口:表示该组件只能使用一次(单次使用后即不可重启)
     */
    interface SingleUse {
    }
}

LifecycleState

​ 组件的生命周期状态枚举。每个状态标记了当前组件是否处于“可用”状态(available),以及对应的生命周期事件名(lifecycleEvent)

public enum LifecycleState {

    // 初始状态,尚未进行任何初始化操作
    NEW(false, null),

    // ================= 初始化阶段 =================

    // 初始化中,调用 init() 时进入此状态,发布 before_init 事件
    INITIALIZING(false, Lifecycle.BEFORE_INIT_EVENT),

    // 初始化完成,进入 INITIALIZED 状态,发布 after_init 事件
    INITIALIZED(false, Lifecycle.AFTER_INIT_EVENT),

    // ================= 启动阶段 =================

    // 启动准备中,准备启动前进入该状态,发布 before_start 事件
    STARTING_PREP(false, Lifecycle.BEFORE_START_EVENT),

    // 正在启动,执行 startInternal() 时进入此状态,发布 start 事件
    STARTING(true, Lifecycle.START_EVENT),

    // 启动完成,组件已处于工作状态,发布 after_start 事件
    STARTED(true, Lifecycle.AFTER_START_EVENT),

    // ================= 停止阶段 =================

    // 停止准备阶段,准备停止时进入该状态,发布 before_stop 事件
    STOPPING_PREP(true, Lifecycle.BEFORE_STOP_EVENT),

    // 正在停止,组件关闭过程中进入该状态,发布 stop 事件
    STOPPING(false, Lifecycle.STOP_EVENT),

    // 停止完成,组件已不可用,发布 after_stop 事件
    STOPPED(false, Lifecycle.AFTER_STOP_EVENT),

    // ================= 销毁阶段 =================

    // 销毁准备阶段,发布 before_destroy 事件
    DESTROYING(false, Lifecycle.BEFORE_DESTROY_EVENT),

    // 销毁完成,组件进入不可恢复终态,发布 after_destroy 事件
    DESTROYED(false, Lifecycle.AFTER_DESTROY_EVENT),

    // ================= 异常状态 =================

    // 异常失败状态,组件启动或运行中发生未处理异常,进入失败态。无生命周期事件发布
    FAILED(false, null);

    /**
     * 当前状态是否为组件的“可用”状态,即是否可对外提供服务(如 STARTING、STARTED 等)
     */
    private final boolean available;

    private final String lifecycleEvent;

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

    public boolean isAvailable() {
        return available;
    }

    public String getLifecycleEvent() {
        return lifecycleEvent;
    }
}

LifecycleBase

LifecycleBaseLifecycle 接口的基础实现类,提供了生命周期控制方法(如 init()start()stop()destroy())的通用模板逻辑。Tomcat 中绝大多数实现了 Lifecycle 接口的核心组件,都会继承该类,从而复用其统一的状态管理和事件分发机制。

​ 核心start方法分析如下,(其余的init,stop等方法差不太多,就不做详细的分析了)

public abstract class LifecycleBase implements Lifecycle {
    /**
     * 启动组件。线程安全,具备幂等性。
     * 
     * 生命周期状态迁移如下:
     * NEW -> INITIALIZED -> STARTING_PREP -> STARTING -> STARTED
     * 如果启动失败,将进入 FAILED 状态。
     */
    public final synchronized void start() throws LifecycleException {

        if (LifecycleState.STARTING_PREP.equals(state) || LifecycleState.STARTING.equals(state) ||
                LifecycleState.STARTED.equals(state)) {
            // 正在启动中或已启动,无视直接返回
            return;
        }

        // ============= 前置状态判断 =================
        if (state.equals(LifecycleState.NEW)) {
            // 如果还是初始化状态,就先初始化
            init();
        } else if (state.equals(LifecycleState.FAILED)) {
            // 若之前启动失败,先尝试停止,清理资源后重新启动
            stop();
        } else if (!state.equals(LifecycleState.INITIALIZED) &&
                !state.equals(LifecycleState.STOPPED)) {
            // 其余非法前置状态,直接异常
            invalidTransition(Lifecycle.BEFORE_START_EVENT);
        }
        // ============== 到这表示前置状态处理完毕,可以真正start了 ===================

        try {
            // 设置状态为 STARTING_PREP,并发布 before_start 事件
            setStateInternal(LifecycleState.STARTING_PREP, null, false);
            // 调用子类实现的实际启动逻辑(模板方法模式)
            startInternal();
            // ============ 走到这,正常情况state就应该为STARTING了 =================

            if (state.equals(LifecycleState.FAILED)) {
                // 启动失败,执行stop
                stop();
            } else if (!state.equals(LifecycleState.STARTING)) {
                // 非STARTING(正常不应该出现,避免子类实现不规范的一种fallback),直接抛异常
                invalidTransition(Lifecycle.AFTER_START_EVENT);
            } else {
                // 正常会走到这,状态自动置为STARTED。并发布 after_start 事件
                setStateInternal(LifecycleState.STARTED, null, false);
            }
        } catch (Throwable t) {
            handleSubClassException(t, "lifecycleBase.startFail", toString());
        }
    }

}

总结

tomcat-lifecycle.png

Lifecycle状态转换图

状态机核心要点:

  • 启动组件必定要先init,也只会调用一次init
  • start和stop状态可以循环相互转化(即STOPPED状态不是终态)
  • NEW可直接到STOPPED状态(很少这么用)
  • DESTROYED才是终态,不可逆转(FAILED都不是终态,它还可以stop() -> startI(),虽然不一定成功)