tomcat7--container

本文详细解析了Tomcat7服务器的启动过程,包括server、service、container及Connector等核心组件的启动顺序和机制,并深入探讨了线程池、类加载器的工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

tomcat 7 启动时 先 启动catalina ,利用 digester 工具包来解析server.xml 创建 server ;

server 包含 service 

service 包含 container 和 Connector ;

container 的体系从高到低 依次为 engine > host >context>wrapper。

server 启动 service代码如下:

@Override
    protected void startInternal() throws LifecycleException {


        fireLifecycleEvent(CONFIGURE_START_EVENT, null);
        setState(LifecycleState.STARTING);


        globalNamingResources.start();
        
        // Start our defined Services
        synchronized (services) {
            for (int i = 0; i < services.length; i++) {
                services[i].start();
            }
        }
    }


(这里为什么要同步呢? 看起来启动server 是在main线程进行的。)

依次启动service ,service启动代码如下:

@Override
    protected void startInternal() throws LifecycleException {

        if(log.isInfoEnabled())
            log.info(sm.getString("standardService.start.name", this.name));
        setState(LifecycleState.STARTING);

        // Start our defined Container first
        if (container != null) {
            synchronized (container) {
                container.start();
            }
        }

        synchronized (executors) {
            for (Executor executor: executors) {
                executor.start();
            }
        }

        // Start our defined Connectors second
        synchronized (connectors) {
            for (Connector connector: connectors) {
                try {
                    // If it has already failed, don't try and start it
                    if (connector.getState() != LifecycleState.FAILED) {
                        connector.start();
                    }
                } catch (Exception e) {
                    log.error(sm.getString(
                            "standardService.connector.startFailed",
                            connector), e);
                }
            }
        }
    }

先启动的是container:

container 体系如下 : 

container 容器有4中实现,级别从高到低为 engine >host  >context >wapper。所有的 容器均继承 containerBase 。

containerbase 包含一个 pipeline 和  startStopExecutor 任务执行器 ;

 每个容器调用containerbase 的方法启动,containerbase 启动代码如下:

        // Start our child containers, if any
        Container children[] = findChildren();
        List<Future<Void>> results = new ArrayList<Future<Void>>();
        for (int i = 0; i < children.length; i++) {
            results.add(startStopExecutor.submit(new StartChild(children[i])));
        }

results.add(startStopExecutor.submit(new StartChild(children[i])));

这里用到了 threadpoolExcuter 封装的线程池,封装成任务执行器;把每一个注册的子容器提交给一个任务执行器来启动

private static class StartChild implements Callable<Void> {

        private Container child;

        public StartChild(Container child) {
            this.child = child;
        }

        @Override
        public Void call() throws LifecycleException {
            child.start();
            return null;
        }
    }
每一个 startChild 线程启动一个container,这是递归调用的,子容器又会启动子容器,最底层的容器最先启动完成。

然后等待直到每一个子容器启动完成:

 for (Future<Void> result : results) {
            try {
                result.get();
            } catch (Exception e) {
                log.error(sm.getString("containerBase.threadedStartFailed"), e);
                fail = true;
            }

        }

子容器全部启动完成之后,启动 pipeline

// Start the Valves in our pipeline (including the basic), if any
        if (pipeline instanceof Lifecycle)
            ((Lifecycle) pipeline).start();

containerbase 持有一个standardPipeline,pipeline 也持有自己所在容器的引用

 /**
     * The Pipeline object with which this Container is associated.
     */
    protected Pipeline pipeline = new StandardPipeline(this);

pipeline启动代码如下:pipeline会先启动server.xml自定义的Valve ,最后启动 basic Valve。

 @Override
    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);
    }

basic Valve 是容器初始化时绑定给pipeline的:

standardEngine 的初始化代码如下:

 /**
     * Create a new StandardEngine component with the default basic Valve.
     */
    public StandardEngine() {

        super();
        pipeline.setBasic(new StandardEngineValve());
        /* Set the jmvRoute using the system property jvmRoute */
        try {
            setJvmRoute(System.getProperty("jvmRoute"));
        } catch(Exception ex) {
            log.warn(sm.getString("standardEngine.jvmRouteFail"));
        }
        // By default, the engine will hold the reloading thread
        backgroundProcessorDelay = 10;

    }

可见,engine 容器的 pipeline绑定的 basic Valve 就是 StandardEngineValve 。

StandardEngineValve 就是一个实例,不包含任何别的组件了,因此Valve 的start() 只是设置一个启动状态,然后什么也不做。


当创建各级容器实例的时候,(创建容器实例在 Catalina 启动Server 之前就完成了。)

1. StandardHost  给子容器 context 绑定了一个监听器。

/**
     * Add a child Container, only if the proposed child is an implementation
     * of Context.
     *
     * @param child Child container to be added
     */
    @Override
    public void addChild(Container child) {

        child.addLifecycleListener(new MemoryLeakTrackingListener());

        if (!(child instanceof Context))
            throw new IllegalArgumentException
                (sm.getString("standardHost.notContext"));
        super.addChild(child);

    }

这个监听器当context启动完成之后,把context 的 classLoader 绑定到host 。记录内存泄漏用。。(控制台用的。。)


2.  Engine

 在Catalina 创建默认的StandardEngine 时,同时也将自己的classLoader 传递给了 StandardEngine, 也就是CommonClassLoader。


3. Contetxt

当使用Digetser创建 Context 时, Context 会创建一个 WabAppLoader 的实例,这个loader 是支持热部署的。

当 Digester 实例化 Context 之后, 还会调用 Context  的 setLoader() 方法,这个方法里启动了WebAppLoader ,调用 它的StartInternal() 方法。

 // Construct a class loader based on our current repositories list
        try {

            classLoader = createClassLoader();
            classLoader.setResources(container.getResources());
            classLoader.setDelegate(this.delegate);
            classLoader.setSearchExternalFirst(searchExternalFirst);
            if (container instanceof StandardContext) {
                classLoader.setAntiJARLocking(
                        ((StandardContext) container).getAntiJARLocking());
                classLoader.setClearReferencesStatic(
                        ((StandardContext) container).getClearReferencesStatic());
                classLoader.setClearReferencesStopThreads(
                        ((StandardContext) container).getClearReferencesStopThreads());
                classLoader.setClearReferencesStopTimerThreads(
                        ((StandardContext) container).getClearReferencesStopTimerThreads());
                classLoader.setClearReferencesHttpClientKeepAliveThread(
                        ((StandardContext) container).getClearReferencesHttpClientKeepAliveThread());
            }

            for (int i = 0; i < repositories.length; i++) {
                classLoader.addRepository(repositories[i]);
            }

            // Configure our repositories
            setRepositories();
            setClassPath();

            setPermissions();

            ((Lifecycle) classLoader).start();

首先创建一个WebAppClassLoader ,这个才是  WebappLoader 这个组件持有的真正的类加载器。

这里那么它的父类加载器是谁呢? 想想上面提到的 Engine 容器的设置的 classLoader ,就是这个Catalina 传递的 CommomClassLoader了。

        if (parentClassLoader == null) {
            parentClassLoader = container.getParentClassLoader();
        }
CommomClassLoader 加载所有Server 都能访问的类库

一个 WebappClassLoader 加载一个 webapp 


server 是在main 线程运行的,service 也是在main 线程运行的,(待续)








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值