Tomcat的各级容器们的职责(中)

Server组件

Server组件具体实现类StandardServer。

Server继承了LifecycleBase,它的生命周期被统一管理


Tomcat的各级容器们的职责(中)



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

@Override
public void addService(Service service) {

    service.setServer(this);

    synchronized (servicesLock) {
        // 长度+1的数组并没有一开始就分配一个很长的数组
        // 而是在添加的过程中动态地扩展数组长度,当添加一个新的Service实例时
        // 会创建一个新数组并把原来数组内容复制到新数组,节省内存
        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);
    }

}


Server组件还需要启动一个Socket来监听停止端口,所以才能通过shutdown命令关闭Tomcat。

上面Catalina的启动方法最后一行代码就是调用Server#await。


在await方法里会创建一个Socket监听8005端口,并在一个死循环里接收Socket上的连接请求,如果有新的连接到来就建立连接,然后从Socket中读取数据;如果读到的数据是停止命令“SHUTDOWN”,就退出循环,进入stop流程。


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继承了LifecycleBase抽象类,此外StandardService中还有一些我们熟悉的组件,比如Server、Connector、Engine和Mapper。


Tomcat支持热部署,当Web应用的部署发生变化,Mapper中的映射信息也要跟着变化,MapperListener就是监听器,监听容器的变化,并把信息更新到Mapper。


Service启动方法

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();
            }
        }
    }
}


Service先后启动Engine、Mapper监听器、连接器。

内层组件启动好了才能对外提供服务,才能启动外层的连接器组件。而Mapper也依赖容器组件,容器组件启动好了才能监听它们的变化,因此Mapper和MapperListener在容器组件之后启动。

上一篇:服务器价格指导 11月双路机架产品导购


下一篇:Maven 安装和配置和 Tomcat 安装和配置