在前面我们介绍了如何通过源码来启动Tomcat,本文我们就来看一下Tomcat是如何一步步启动的,以及在启动过程中,不同的组件是如何加载的。
一般,我们可以通过 Tomcat 的 /bin 目录下的脚本 startup.sh 来启动 Tomcat,如果是window那就用startup.bat来启动。 那我们执行了这个脚本后发生了什么呢?
目录
1.整体结构
在一篇中,我们看到tomcat启动是从类Bootstrap里的Main方法开始的,因此对于Tomcat而说,Bootstrap就是创造万物的工具。
之后的工作,可以通过下面这张流程图来了解一下。
- Tomcat 本质上是一个 Java 程序,因此 startup.sh 脚本最 核心的工作就是启动一个 JVM 来运行 Tomcat 的启动类 Bootstrap。
- Bootstrap 的主要任务是初始化 Tomcat 的类加载器,并且创建 Catalina。
- Catalina 是一个启动类,它通过解析 server.xml来创建相应的组件,并调用 Server 的 start 方法。
- Server 组件的职责就是管理 Service 组件,它会负责调用 Service 的 start() 方法。
- Service 组件的职责就是管理连接器和顶层容器 Engine,因此它会调用连接器和 Engine 的 start 方法。
这样 Tomcat 的启动就算完成了。下面我来详细介绍一下上面这个启动过程中提到的几个非常关键的启动类和组件。
如果我们以一个互联网大厂, 比如腾宝,那么 Bootstrap就是创始人马老师,而Server则是不同的事业群,例如支付宝、天猫、阿里云等等。Service 是事业群总经理,一般事业群里会有多个部门,而在Tomcat里,Service管理两个职能部门:一个是对外的市场部,也就是连接器组件;另一个是对内的研发部,也就是容器组件。
再向下,Engine 则是研发部经理,之后的Service就是具体干活的你和我,在Tomcat里就是Servlet。
2.文件解析与组件创建器—Catalina
Catalina 的主要任务就是创建 Server,它不是直接 new 一个 Server 实例就完事了,而是需要解析 server.xml,所以打开Catalina类的代码,我们会发现很多篇幅都是和解析xml或者Digester类有关系,后者也是解析文件的。
Catalina的作用就是把在 server.xml 里配置的各种组件一一创建出来,接着调用 Server 组件的 init 方法和 start 方法,这样整个 Tomcat 就启动起来了。作为“管理者”,Catalina 还需要处理各种“异常”情况,比如当我们通过“Ctrl + C”关闭 Tomcat 时,Tomcat 将如何优雅的停止并且清理资源呢?因此 Catalina 在 JVM 中注册一个“关闭钩子”。
public void start() {
//1. 如果持有的 Server 实例为空,就解析 server.xml 创建出来
if (getServer() == null) {
load();
}
//2. 如果创建失败,报错退出
if (getServer() == null) {
log.fatal(sm.getString("catalina.noServer"));
return;
}
//3. 启动 Server
try {
getServer().start();
} catch (LifecycleException e) {
return;
}