Tomcat版本:8.5.50 , 下载地址: tomcat 下载 .
Tomcat过于复杂,总结难免出错,请根据自己的实际理解进行验证.
整体结构
整体结构图(根据线上部署稍有删减)
- 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/class和WEB-INF/lib下边的文件.
WebResourceRoot是Resource的一层抽象,主要是维护并读取WEB-INF/class和WEB-INF/lib**下边的文件.
Container(容器)的概念是在Engine处才开始体现的,从代码来看就是看有没有实现Container接口
UML图例
如果不支持看大图,可以复制图片地址到浏览器看大图
**
语雀画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(这里是启动一个异步线程处理)
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的启动初看比较复杂,但是在理解他们的Class引用关系后,就会变的简单很多,类的继承关系也很复杂,但是我可以抓住她运行时的核心类 LifecycleBase和ContainerBase 会好理解一点。