美文网首页
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