Tomcat的顶层结构以及启动过程

目录

  • Tomcat的源码
  • Tomcat的顶层结构
    • 简介
    • 结构图
  • 启动过程
    • 时序图
    • Bootstrap的启动过程
    • Catalina的启动过程
    • Server的启动过程
    • Service的启动过程

本文章仅作为了解tomcat的基础不做深入研究,文章来源:《看透Spring MVC源代码分析与实践》韩璐彪 著

Tomcat的源码

GitHub地址

Tomcat的顶层结构

简介

Tomcat中最顶层的容器叫Server,代表整个服务器;
Server中至少包含一个Service
Service用于提供具体服务:Service主要包含两部分:
ConnectorContainer

  • Connector是处理连接相关的内容,包含Socket与request、response的转换;
  • Container则用于封装和管理Servlet以及调用Servlet中的doGet方法等(处理request请求)

结构图

Tomcat的顶层结构以及启动过程_第1张图片
Tomcat中的Server由org.apache.catalina.startup.Catalina来操作,Catalina是整个Tomcat的管理类,他里面的三个方法loadstartstop就是分别用来加载、启动、停止整个服务器,

  • load主要读取conf/serve.xml文件 获取Server相关的配置(端口、以及个别应用Service的部署配置一类)进行初始化;
  • start方法就是用来启动Server
  • stop就是为了停止Server

通过研读该方法可以发现该方法调用了Server中的start,而Server的start又调用了Service的start,只不过是Catalina调用了Server一次start方法,而Server调用了每一个Service的start方法,load与stop均是如此,

启动过程

时序图

Bootstrap Catalina StandardSenrver StandardSenvice Container MapperUstener Executor Connector 1:main() 1.1:init() 1.2:load() 1.2.1:load() 1.2.1.1:init() 1.2.1.1.1:init() 1.2.1.1.1.1:init() 1.2.1.1.1.2:init() 1.2.1.1.1.3:init() 1.2.1.1.1.4:init() 1.3:start() 1.3.1:start() 1.3.1.1:start() 1.3.1.1.1:start() 1.3.1.1.1.1:start() 1.3.1.1.1.2:start() 1.3.1.1.1.3:start() 1.3.1.1.1.4:start() Bootstrap Catalina StandardSenrver StandardSenvice Container MapperUstener Executor Connector

Bootstrap的启动过程

代码连接

Tomcat的入口main(Java写的嘛,自然是通过main方法启动)并不在Catalina类中,正式启动是在org.apache.catalina.startup.Bootstrap中。这个类作用是转化Catalina的实例并调用相应的方法(Bootstrap与Catalina的关系像是一种代理关系),创建了实例后通过脚本catalina.bat/catalina.sh传递过来的参数进行相应配置并调用load、start、stop方法根据代码可知,start与load会受到参数影响,而stop不会也没必要

注意:该类中包含比较多的静态代码建议多读一读

Catalina的启动过程

代码连接
作为正式的服务器启动器,该类有三个主要方法setAwait、load和start方法,setAwait方法用于设置Server启动完成后是否进入等待状态的标志,这个可以通过配置完成设置,由上面的Bootstrap中的main方法反射并固定为true,Bootstrap的main方法主要调用setAwait如下

 Bootstrap bootstrap = new Bootstrap();
 ···
 daemon = bootstrap;
 ···
 else if (command.equals("start")) {
                daemon.setAwait(true);//本行***
                daemon.load(args);
                daemon.start();
                if (null == daemon.getServer()) {
                    System.exit(1);
                }
            }
···
 public void setAwait(boolean await)
        throws Exception {

        Class paramTypes[] = new Class[1];
        paramTypes[0] = Boolean.TYPE;
        Object paramValues[] = new Object[1];
        paramValues[0] = Boolean.valueOf(await);
        Method method =
            catalinaDaemon.getClass().getMethod("setAwait", paramTypes);
        method.invoke(catalinaDaemon, paramValues);

    }

load方法与start不做赘述,看代码比较好比较复杂,反射用了很多,总的来说这两个方法的主要作用如下:

  • load:用于加载配置文件,创建并初始化Server(调用Server.init方法)
  • start方法用于启动服务器(调用Server.start方法)

Server的启动过程

代码链接
从前面讲述结构时已经表述,一个Server下存在多个Service,为了方便操作Server,Server类中提供了addService、removeService方法来添加和删除Service,并且Server的init方法和start方法分别循环调用了每个Service的init方法和start方法来启动所有的Service
Server的默认实现是org.apache.catalina.core.StandardServer
继承关系为: StandardServer<-LifecycleMBeanBase-
init和start方法就在LifecycleBase,并且该类提供了initInternal方法和startInternal方法作为模板方法,由子类具体实现,这两个方法与Tomcat的生命周期管理有关,在此不做陈述,我会单独发一篇说明Tomcat的生命周期的管理方式的文章

Service的启动过程

代码链接
Service的默认实现是org.apache.catalina.core.StandardService,
继承关系为: StandardService<-LifecycleMBeanBase-
让我们看一下init和start的模板方法:

//强烈建议读源码,理解较为深刻
//init模板方法
 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) {
                connector.init();
            }
        }
    }
//start模板方法
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) {
                // If it has already failed, don't try and start it
                if (connector.getState() != LifecycleState.FAILED) {
                    connector.start();
                }
            }
        }
    }

可以看出StandardService中的initInternal和starInternal主要调用了container、executor、mapperListener以及connectors的init和start方法,其中mapperListener是用来箭筒container容器变化的,executors使用在connectors中管理线程的线程池,具体用法参考conf/server.xml,搜索关键字Executor Connector,该配置文件中大量用法都被注释起来了,有兴趣可以研究下

当所有的Service运行完start方法,那么整个tomcat就启动了,接下来就可以通过项目访问地址访问web项目了。

你可能感兴趣的:(Tomcat,应用服务器)