Tomcat学习笔记之启动分析(Container)(六)

前言

通过上面一篇的介绍,Service主要启动了Container和Connector,我们先来看Container容器。

Container的子类关系图

Container关系图.png

由上图知道,Container有四个子容器,分别为:
Engine:引擎,用来管理多个站点,一个Service最多只能有一个;
Host:代表一个站点,或者叫做虚拟主机,一个Engine可以包含多个Host;
Context:代表一个应用,一个Host可以包含多个Context;
Wrapper:每个Wrapper封装着一个Servlet,一个Context可以包含多个Wrapper。
下面我们一个一个来介绍。

ContainerBase

同样ContainerBase也遵循Lifecycle机制。

  • initInternal()方法
protected void initInternal() throws LifecycleException {
        reconfigureStartStopExecutor(getStartStopThreads());
        super.initInternal();
    }


    private void reconfigureStartStopExecutor(int threads) {
        // threads一般默认为1,startStopExecutor用来处理其子容器的启动和停止事件
        if (threads == 1) {
            // Use a fake executor
            if (!(startStopExecutor instanceof InlineExecutorService)) {
                startStopExecutor = new InlineExecutorService();
            }
        } else {
            // Delegate utility execution to the Service
            Server server = Container.getService(this).getServer();
            server.setUtilityThreads(threads);
            startStopExecutor = server.getUtilityExecutor();
        }
    }

这里主要初始化startStopExecutor线程池,用来处理其子容器的启动和停止事件的线程池。

  • startInternal()方法
protected synchronized void startInternal() throws LifecycleException {

        // Start our subordinate components, if any
        logger = null;
        getLogger();
        //1. 集群和认证相关
        Cluster cluster = getClusterInternal();
        if (cluster instanceof Lifecycle) {
            ((Lifecycle) cluster).start();
        }
        Realm realm = getRealmInternal();
        if (realm instanceof Lifecycle) {
            ((Lifecycle) realm).start();
        }

        //2. 启动子容器
        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])));
        }

        MultiThrowable multiThrowable = null;

        for (Future<Void> result : results) {
            try {
                result.get();
            } catch (Throwable e) {
                log.error(sm.getString("containerBase.threadedStartFailed"), e);
                if (multiThrowable == null) {
                    multiThrowable = new MultiThrowable();
                }
                multiThrowable.add(e);
            }

        }
        if (multiThrowable != null) {
            throw new LifecycleException(sm.getString("containerBase.threadedStartFailed"),
                    multiThrowable.getThrowable());
        }

        //3. 启动管道
        if (pipeline instanceof Lifecycle) {
            ((Lifecycle) pipeline).start();
        }
        //4. 设置状态,发送通知
        setState(LifecycleState.STARTING);

        //5. 如果backgroundProcessorDelay>0,启动定时器进行延时处理
        if (backgroundProcessorDelay > 0) {
            monitorFuture = Container.getService(ContainerBase.this).getServer()
                    .getUtilityExecutor().scheduleWithFixedDelay(
                            new ContainerBackgroundProcessorMonitor(), 0, 60, TimeUnit.SECONDS);
        }
    }

这里主要通过startStopExecutor线程池来执行子容器的启动,并且启动子容器对应的管道(每个子容器都有自己对应的管道,后面会介绍)。

ValveBase&&StandardPipeline

ValveBase作为所有子容器阀的抽想实现类,其初始化执行了其父类LifecycleMBeanBase的初始化方法,启动仅仅设置了容器的状态,所以这里不介绍了。

protected void initInternal() throws LifecycleException {
        super.initInternal();
        containerLog = getContainer().getLogger();
    }

    protected synchronized void startInternal() throws LifecycleException {
        setState(LifecycleState.STARTING);
    }

StandardPipeline作为最基础的管道,仅仅实现了启动方法。

protected synchronized void startInternal() throws LifecycleException {

        // Start the Valves in our pipeline (including the basic), if any
        Valve current = first;
        if (current == null) {
            current = basic;
        }
        while (current != null) {
            if (current instanceof Lifecycle)
                ((Lifecycle) current).start();
            current = current.getNext();
        }

        setState(LifecycleState.STARTING);
    }

该方法主要循环执行了每一个管道的start方法并设置其生命状态。
具体管道的介绍放在下一篇,这里不做过多描述。

StandardEngine

作为Engine的默认实现类,我们来看下他的启动。

  • initInternal()方法
protected void initInternal() throws LifecycleException {
        // Ensure that a Realm is present before any attempt is made to start
        // one. This will create the default NullRealm if necessary.
        getRealm();
        super.initInternal();
    }

这里调用其父类的初始化方法,上面已经介绍过了。

  • startInternal()方法
protected synchronized void startInternal() throws LifecycleException {

        // Log our server identification information
        if (log.isInfoEnabled()) {
            log.info(sm.getString("standardEngine.start", ServerInfo.getServerInfo()));
        }

        // Standard container startup
        super.startInternal();
    }

同样也是调用其父类的启动方法。

StandardEngineValve

默认使用其父类ValveBase的初始化和启动,不介绍。

StandardHost

Host的默认实现类,初始化和启动都是调用其父类的方法。

StandardHostValve

Host的默认管道类,初始化和启动都是调用其父类的方法。

StandardWrapper

Wrapper的默认实现类,初始化和启动都是调用其父类的方法。

StandardWrapperValve

Wrapper的默认管道类,初始化和启动都是调用其父类的方法。

总结

这里涉及到重要的管道内容,后面会有一篇专门介绍管道。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 13,796评论 1 32
  • 面向对象主要针对面向过程。 面向过程的基本单元是函数。 什么是对象:EVERYTHING IS OBJECT(万物...
    sinpi阅读 4,751评论 0 4
  • 这是16年5月份编辑的一份比较杂乱适合自己观看的学习记录文档,今天18年5月份再次想写文章,发现简书还为我保存起的...
    Jenaral阅读 7,891评论 2 9
  • http://liuxing.info/2017/06/30/Spring%20AMQP%E4%B8%AD%E6%...
    sherlock_6981阅读 16,109评论 2 11
  • 官方文档 初始化 Initialization是为准备使用类,结构体或者枚举实例的一个过程。这个过程涉及了在实例里...
    hrscy阅读 4,801评论 0 1