美文网首页
Tomcat学习笔记之启动分析(Container)(六)

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

作者: 夏目手札 | 来源:发表于2019-05-07 21:50 被阅读0次

前言

通过上面一篇的介绍,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的默认管道类,初始化和启动都是调用其父类的方法。

总结

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

相关文章

网友评论

      本文标题:Tomcat学习笔记之启动分析(Container)(六)

      本文链接:https://www.haomeiwen.com/subject/bwdxnqtx.html