Tomcat源码架构笔记(start启动篇)
warning:
这篇文章距离上次修改已过1786天,其中的内容可能已经有所变动。
在上篇文章中,我们讲到了Tomcat启动时候的两大关键阶段之一的init初始化阶段,简单的走了一下初始化的流程。
- init初始化阶段(传送门)
- start启动阶段
这里我们继续探究Tomcat start启动阶段的运行过程。

Tomcat start启动阶段

启动流程开始

调用Catalina.satrt()方法

启动Server

向统一生命周期管理类报道

启动service子容器

再次向统一生命周期管理类报道

启动Engine子容器
info:开始走启动Engine的分支了

再次向统一生命周期管理类报道

调用父类startInternal方法

循环启动线程池
线程池提交线程,如果有多个Host,那么就可以多个线程并行实例化Host,加快Tomcat启动速度


startChild核心逻辑

再次向统一生命周期管理类报道

调用父类startInternal方法

Host实例化
Host的实例化,是通过设置容器生命周期状态(STARTING)。
通过触发Host生命周期事件fireLifecycleEvent
来执行后续工作(实例化Context,交给HostConfig进行,HostConfig是生命周期事件监听器,触发对应事件)。

触发start生命周期事件

循环调用监听器

监听器进行业务逻辑处理


部署webapp应用

deployApps,处理Host下多个应用

以多线程的方式处理Host下多个应用(目录模式)
deployDirectories,处理host下以目录方式部署的app-context
app处理的时候也是以多线程方式处理(results.add(es.submit(new DeployDirectory(this, cn, dir)));
)

run方法

webapp 部署的具体方法

host.addChild(centext)时才去触发Context实例核心内容,比如wrapper-serlvet的封装
调用父类addChild方法

进一步调用

处理具体的Context


再次向统一生命周期管理类报道

创建工作目录

设置类加载器

具体的读取web.xml封装wrapper
Context具体的读取web.xml封装wrapper过程使用事件驱动,交给了ContextConfig(它也是一个事件监听器)

加载初始化Servlet



判断是否在启动是加载初始化

调用wrapper.load()

实例化Servlet



连接器启动
info:开始走连接器启动分支了

向统一生命周期管理类报道

PortocolHandler启动

EndPoint初始化


NIO模型


创建Acceptor


OK,到此Tomcat的启动流程大概走完了,下一篇我们去看看Servlet处理请求的逻辑是什么样的。