Tomcat启动分析(四) - Server、Service与Executor

在分析Lifecycle接口之后,本文分析Server、Service和Executor组件的初始化和启动过程。

Server组件

Server表示整个容器,Server接口的唯一实现类是StandardServer类,它继承了LifecycleMBeanBase类。它的initInternal方法很简单,初始化各Service。

@Override
protected void initInternal() throws LifecycleException {
    super.initInternal();
    // 省略与JMX有关的代码
    // Initialize our defined Services
    for (int i = 0; i < services.length; i++) {
        services[i].init();
    }
}

StandardServer类的startInternal方法主要做了以下几件事:

  • 触发CONFIGURE_START_EVENT事件;
  • 启动命名服务(好像与JNDI有关,不太确定);
  • 启动添加的各Service。
@Override
protected void startInternal() throws LifecycleException {
    fireLifecycleEvent(CONFIGURE_START_EVENT, null);
    setState(LifecycleState.STARTING);

    globalNamingResources.start();

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

Service组件

Service处于Server和Engine之间,用来将Connector绑定到Engine上。Service接口的唯一实现类是StandardService类,它同样继承了LifecycleMBeanBase类。它的initInternal方法做了以下几件事:

  • 初始化添加的Engine;
  • 初始化添加的各Executor;
  • 初始化与该Service关联的MapperListener,这个监听器用来注册该Service内的Host和Context以便在请求到来时找到正确的Host和Context;
  • 初始化添加的各Connector。
@Override
protected void initInternal() throws LifecycleException {
    super.initInternal();
    if (engine != null) {
        engine.init();
    }
    // Initialize any Executors
    for (Executor executor : findExecutors()) {
        if (executor instanceof JmxEnabled) {
            ((JmxEnabled) executor).setDomain(getDomain());
        }
        executor.init();
    }
    // Initialize mapper listener
    mapperListener.init();
    // Initialize our defined Connectors
    synchronized (connectorsLock) {
        for (Connector connector : connectors) {
            try {
                connector.init();
            } catch (Exception e) {
                String message = sm.getString("standardService.connector.initFailed", connector);
                log.error(message, e);
                if (Boolean.getBoolean("org.apache.catalina.startup.EXIT_ON_INIT_FAILURE"))
                    throw new LifecycleException(message);
            }
        }
    }
}

StandardService类的startInternal方法在main线程按顺序做了以下几件事:

  • 启动添加的Engine;
  • 启动添加的各Executor;
  • 启动与该Service关联的MapperListener,注册该Service内的各Host和Context;
  • 启动添加的各Connector。
@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 (engine != null) {
        synchronized (engine) {
            engine.start();
        }
    }

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

    mapperListener.start();

    // Start our defined Connectors second
    synchronized (connectorsLock) {
        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);
            }
        }
    }
}

Executor组件

Tomcat的Executor接口继承了Java的Executor接口,其唯一实现类是StandardThreadExecutor类,它同样继承了LifecycleMBeanBase类,initInternal方法没有做自己的事情。

@Override
protected void initInternal() throws LifecycleException {
    super.initInternal();
}

StandardThreadExecutor类的startInternal方法如下:

@Override
protected void startInternal() throws LifecycleException {

    taskqueue = new TaskQueue(maxQueueSize);
    TaskThreadFactory tf = new TaskThreadFactory(namePrefix,daemon,getThreadPriority());
    executor = new ThreadPoolExecutor(getMinSpareThreads(), getMaxThreads(), maxIdleTime, TimeUnit.MILLISECONDS,taskqueue, tf);
    executor.setThreadRenewalDelay(threadRenewalDelay);
    if (prestartminSpareThreads) {
        executor.prestartAllCoreThreads();
    }
    taskqueue.setParent(executor);

    setState(LifecycleState.STARTING);
}
  • TaskThreadFactory实现了ThreadFactory接口,新线程的名字是namePrefix加计数,namePrefix和其他属性可以在文件servel.xml中设置,也可以通过StandardThreadExecutor的setter方法设置;
  • StandardThreadExecutor用上述线程工厂为自己创建了一个ThreadPoolExecutor。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容