【Tomcat9源码分析】生命周期、启动、停止概述
转载请注明出处:http://blog.csdn.net/linxdcn/article/details/73350812
1 前言
在Tomcat启动时,会读取server.xml
文件创建Server
, Service
, Connector
, Engine
, Host
, Context
, Wrapper
等组件,各个组件的介绍可以参考Tomcat组件与框架
各组件创建完成后,Tomcat负责管理它们的生命周期,本文先介绍Tomcat中的组件生命周期管理,然后再介绍Tomcat的启动与停止。
2 生命周期管理
2.1 Lifecycle
Tomcat中的所有组件都继承了Lifecycle
接口,Lifecycle
接口定义了一整套生命周期管理的函数,从组件的新建、初始化完成、启动、停止、失败到销毁,都遵守同样的规则,Lifecycle
组件的状态转换图如下。
Lifecycle状态转移图
Lifecycle
接口的主要方法如下,正常的调用顺序是init()
->start()
->destroy()
,父组件的init()
和start()
会触发子组件的init()
和start()
,所以Tomcat中只需调用Server
组件的init()
和start()
即可。
public interface Lifecycle {
public void init() throws LifecycleException;
public void start() throws LifecycleException;
public void stop() throws LifecycleException;
public void destroy() throws LifecycleException;
public LifecycleState getState();
public void addLifecycleListener(LifecycleListener listener);
public LifecycleListener[] findLifecycleListeners();
public void removeLifecycleListener(LifecycleListener listener);
}
每个实现组件都继承自LifecycleBase
,LifecycleBase
实现了Lifecycle
接口,当容器状态发生变化时,都会调用fireLifecycleEvent
方法,生成LifecycleEvent
,并且交由此容器的事件监听器处理。
public abstract class LifecycleBase implements Lifecycle {
protected void fireLifecycleEvent(String type, Object data) {
LifecycleEvent event = new LifecycleEvent(this, type, data);
for (LifecycleListener listener : lifecycleListeners) {
listener.lifecycleEvent(event);
}
}
}
2.2 LifecycleListener与LifecycleEvent
在Lifecycle
接口中,还看到LifecycleListener
,这是用来监听Lifecycle
发生的事件,LifecycleListener
接口只定义了一个回调函数。
public interface LifecycleListener {
/**
* Acknowledge the occurrence of the specified event.
*
* @param event LifecycleEvent that has occurred
*/
public void lifecycleEvent(LifecycleEvent event);
}
3 Tomcat启动
下面来看看在执行tomcat/bin/startup.sh
脚本后发生了什么事。执行该脚本等价于执行org.apache.catalina.startup.Bootstra
类的main
方法,并传入start
参数。
package org.apache.catalina.startup;
public final class Bootstrap {
public static void main(String args[]) {
if (daemon == null) {
Bootstrap bootstrap = new Bootstrap();
try {
// 1 调用Bootstrap类的init方法
bootstrap.init();
} catch (Throwable t) {
// 省略代码
}
daemon = bootstrap;
} else {
// 省略代码
}
try {
String command = "start";
// 省略代码
if (command.equals("start")) {
daemon.setAwait(true);
// 2 调用Bootstrap类的load方法
daemon.load(args);
// 3 调用Bootstrap类的load方法
daemon.start();
}
} catch (Throwable t) {
// 省略代码
}
}
}
主要步骤如下:
- 新建
Bootstrap
对象daemon
,并调用其init()
方法- 初始化Tomcat的类加载器
- 用反射实例化
org.apache.catalina.startup.Catalina
对象catalinaDaemon
- 调用
daemon
的load
方法,实质上调用了catalinaDaemon
的load
方法- 加载和解析server.xml配置文件
- 调用
daemon
的start
方法,实质上调用了catalinaDaemon
的start
方法- 启动
Server
组件,Server
的启动会带动其他组件的启动,如Service
,Container
,Connector
- 调用catalinaDaemon的await方法循环等待接收Tomcat的shutdown命令
- 启动
4 Tomcat停止
启动部分最后介绍了catalinaDaemon调用await等待停止命令,我们一般是通过执行tomcat/bin/shutdown.sh
来关闭Tomcat,等价于执行org.apache.catalina.startup.Bootstra
类的main
方法,并传入stop
参数。
package org.apache.catalina.startup;
public final class Bootstrap {
public static void main(String args[]) {
if (daemon == null) {
Bootstrap bootstrap = new Bootstrap();
try {
// 1 调用Bootstrap类的init方法
bootstrap.init();
} catch (Throwable t) {
// 省略代码
}
daemon = bootstrap;
} else {
// 省略代码
}
try {
String command = "start";
// 省略代码
if (command.equals("stop")) {
// 2 调用Bootsrap类的stopServer方法
daemon.stopServer(args);
}
} catch (Throwable t) {
// 省略代码
}
}
}
- 新建
Bootstrap
对象daemon
,并调用其init()
方法- 初始化Tomcat的类加载器
- 用反射实例化
org.apache.catalina.startup.Catalina
对象catalinaDaemon
- 调用
daemon
的stopServer
方法,实质上调用了catalinaDaemon
的stopServer
方法- 解析
server.xml
文件,构造出Server容器 - 获取Server的socket监听端口和地址,创建Socket对象连接启动Tomcat时创建的ServerSocket,最后向ServerSocket发送
SHUTDOWN
命令 - 运行中的Server调用
stop
方法停止
- 解析
5 总结
Tomcat启动与关闭流程
6 参考
http://tomcat.apache.org/tomcat-9.0-doc/architecture/startup/serverStartup.txt
http://tomcat.apache.org/tomcat-9.0-doc/architecture/startup/serverStartup.pdf
http://blog.csdn.net/beliefer/article/details/51585006
转载请注明出处:http://blog.csdn.net/linxdcn/article/details/73350812
上一篇: CUDA学习(四十七)
下一篇: CentOS7安装MySQL5.7