tomcat系列之六:Tomcat顶层组件

一,当启动Tomcat后,各个组件都做了什么

当执行 startup.sh脚本来启动Tomcat后,

1,Tomcat本质上是一个Java程序,所以 startup.sh脚本会启动一个JVM来运行Tomcat的启动类 Bootstrap

2,Bootstrap是初始化 Tomcat 的类加载器,并且创建Catalina

3,Catalina 是一个启动类,它可以解析 server.xml,创建相应的组件,并且调用 Server 的 start 方法。

4,Server组件用来管理 Service组件,它可以调用Service的start方法

5,Service组件的职责就是管理连接器和顶层容器Engine,它可以调用连接器 和 Engine的start方法

二,Catalina

Catalina的任务就是创建 Server,它通过解析 server.xml ,把在 server.xml 中配置的各个组件创建出来,然后调用Server组件的init方法和start方法,这样Tomcat就启动了。

public void start() {
    //1. 如果持有的 Server 实例为空,就解析 server.xml 创建出来
    if (getServer() == null) {
        load();
    }
    //2. 如果创建失败,报错退出
    if (getServer() == null) {
        log.fatal(sm.getString("catalina.noServer"));
        return;
    }

    //3. 启动 Server
    try {
        getServer().start();
    } catch (LifecycleException e) {
        return;
    }

    // 创建并注册关闭钩子
    if (useShutdownHook) {
        if (shutdownHook == null) {
            shutdownHook = new CatalinaShutdownHook();
        }
        Runtime.getRuntime().addShutdownHook(shutdownHook);
    }

    // 用 await 方法监听停止请求
    if (await) {
        await();
        stop();
    }
}
扫描二维码关注公众号,回复: 6355901 查看本文章

那么,Tomcat是如何停止和清理资源的呢?

首先,Catalina在JVM中注册一个 “关闭钩子”,这个钩子可以在关闭时做一些清理操作,比如将缓存数据刷到磁盘上。这个钩子其实就是一个线程,JVM在停止之前会尝试执行这个线程的run方法。

CatalinaShutdownHook:

protected class CatalinaShutdownHook extends Thread {

    @Override
    public void run() {
        try {
            if (getServer() != null) {
                Catalina.this.stop();
            }
        } catch (Throwable ex) {
           ...
        }
    }
}

Tomcat的 “关闭钩子” 实际上就执行了 Server的stop方法,Server的stop方法会释放和清理所有的资源。

三,Server组件

具体实现类:StandardServer。

Server的子组件是Service,所以它要管理Service的生命周期。在Server启动时,需要调用Service组件的启动方法,在停止时调用它们的停止方法。Server在内部维护了Service组件,通过数组来保存。Server如何添加一个Service到数组中?

@Override
public void addService(Service service) {

    service.setServer(this);

    synchronized (servicesLock) {
        // 创建一个长度 +1 的新数组
        Service results[] = new Service[services.length + 1];
        
        // 将老的数据复制过去
        System.arraycopy(services, 0, results, 0, services.length);
        results[services.length] = service;
        services = results;

        // 启动 Service 组件
        if (getState().isAvailable()) {
            try {
                service.start();
            } catch (LifecycleException e) {
                // Ignore
            }
        }

        // 触发监听事件
        support.firePropertyChange("service", null, service);
    }

}

四,Service组件

Service组件的具体实现类:StandardService。

public class StandardService extends LifecycleBase implements Service {
    // 名字
    private String name = null;
    
    //Server 实例
    private Server server = null;

    // 连接器数组
    protected Connector connectors[] = new Connector[0];
    private final Object connectorsLock = new Object();

    // 对应的 Engine 容器
    private Engine engine = null;
    
    // 映射器及其监听器
    protected final Mapper mapper = new Mapper();
    protected final MapperListener mapperListener = new MapperListener(this);

可以看到StandardService中的组件有:Connector,Engine,Mapper,MapperListener(这是一个监听器,当Web应用的部署发生变化时,把信息更新到Mapper中,热部署时用到)。

StandardService中的启动方法:

protected void startInternal() throws LifecycleException {

    //1. 触发启动监听器
    setState(LifecycleState.STARTING);

    //2. 先启动 Engine,Engine 会启动它子容器
    if (engine != null) {
        synchronized (engine) {
            engine.start();
        }
    }
    
    //3. 再启动 Mapper 监听器
    mapperListener.start();

    //4. 最后启动连接器,连接器会启动它子组件,比如 Endpoint
    synchronized (connectorsLock) {
        for (Connector connector: connectors) {
            if (connector.getState() != LifecycleState.FAILED) {
                connector.start();
            }
        }
    }
}

注意启动顺序:先启动Engine组件,再启动Mapper监听器,最后才是启动连接器。(符合先内层,后外层)

五,Engine组件

具体实现类:StandardEngine,Engine本质是一个容器,它继承了ContainerBase基类,并实现Engine接口

public class StandardEngine extends ContainerBase implements Engine {
}

Engine的子容器是Host,它持有一个Host容器的数组,

CatalinaShutdownHook

极客时间版权所有: https://time.geekbang.org/column/article/97603:

猜你喜欢

转载自www.cnblogs.com/inspred/p/10979366.html