Tomcat版本:8.5.50 , 下载地址: tomcat 下载 .

Tomcat过于复杂,总结难免出错,请根据自己的实际理解进行验证.

整体结构

整体结构图(根据线上部署稍有删减)

image.png

  • Tomcat: 作为一个Http服务器对外提供web服务.
  • Server: Servlet 容器,会包含多个Service(实际线上部署只有一个Service) , 默认实现是 StandardServer.
  • Service: 主要由多个Connector(处理即将到来的 Http(http请求为例) 请求)+Engine组成.
  • Connector: 解析并且处理http请求,转发到CoyoteAdapter.
  • Engine: Catalina servlet 引擎,直接子容器是Context , 每一个Service都只有一个.
  • Context: 代表了一个web应用,线上就是一个Context., 标准实现是 StandardContext.


Loader 是
Context的(类)加载器,负载加载Context下边的 WEB-INF/classWEB-INF/lib下边的文件.
WebResourceRoot是Resource的一层抽象,主要是维护并读取
WEB-INF/classWEB-INF/lib**下边的文件.

Container(容器)的概念是在Engine处才开始体现的,从代码来看就是看有没有实现Container接口

**

UML图例


如果不支持看大图,可以复制图片地址到浏览器看大图
Tomcat 结构 - 图2**

语雀画UML图还在探索中,这里依赖关系就没有画出来了,简单点就是 Server—>Service—>Engine—>Context**

这个类图是使用 语雀 画的,肯定没有自动生成的好看,但是比起自动生成,体会更深刻一些,有兴趣到同学可以自行画一下,这里稍微有些乱,简单讲解一下

这里所有的class基本上都实现了或者是间接实现了 Lifecycle 接口,主要入口是 Server(StandardServer).他们都继承了LifecycleBase,初始化和启动会去执行对应的 init 和 start 方法,如果debug会多次进入这里,第一次会稍微有点乱,需要理解各个Class之间的依赖关系。

通过Lifecycle作为纽带,以及Class之间的依赖关系,Tomcat启动的时候可以一级一级的启动所有的Service和Engine(容器)等子类

简单描述

开始是Server.init,一级一级的传递给所有依赖的Class,对应都会去执行init,然后是start,start的流程和init是一致的。

当Server.start 启动时,先启动内部的Service.start, Service 先启动下一级的Connector和Engine,Engine启动Context(这里是启动一个异步线程处理)

  1. startStopExecutor.submit(new StartChild(children[i])); 线程池的名字是 域名-startStop-n

Context里边设置Loader(类加载器),加载ServletContainerInitializer并调用onStartup,执行Listener启动,Filter启动,任意初始化失败都会导致Context启动失败,但是不会影响到Tomcat的正常启动,最后加载Servlet,根据load-start-up>=1来初始化Servlet。到这里基本上就执行完毕了

上面也可以看到Pipeline, 她的的使用是典型的责任链模式 , 通过Pipeline可以将Engine/Host/Context串行联系起来,他们的纽带是 Valve 接口。使用责任链模式可以快速方便的进行拓展。

时序图


Tomcat 结构 - 图3 大体上是这样的,具体的细节就需要看代码了

总结

Tomcat的启动初看比较复杂,但是在理解他们的Class引用关系后,就会变的简单很多,类的继承关系也很复杂,但是我可以抓住她运行时的核心类 LifecycleBase和ContainerBase 会好理解一点。