Tomcat源码架构笔记(start启动篇)
warning:
这篇文章距离上次修改已过1614天,其中的内容可能已经有所变动。
在上篇文章中,我们讲到了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处理请求的逻辑是什么样的。