您的位置:首页 > 运维架构 > Tomcat

tomcat7--container

2014-02-25 18:21 459 查看
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 线程运行的,(待续)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: