一、Tomcat请求流程
组件是如何创建,初始化,销毁的呢,管理他们的生命周期是一个很关键的问题?如何实现一键启动?
答:tomcat的核心组件都抽象出公共的部分 lifecycle接口其中定义了:init()、start()、stop() 和 destroy()这么几个核心方法;在父组件中创建的时候需要调用子组件的init方法。所以只要调用顶层的 Service的init方法,整个tomcat就启动了。
这是lifecyle的模版方法
@Override
public final synchronized void init() throws LifecycleException {
// 1、判断状态
if (!state.equals(LifecycleState.NEW)) {
invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
}
try {
// 2 触发 INITIALIZING 事件的监听器
setStateInternal(LifecycleState.INITIALIZING, null, false);
// 3 调用子类初始化方法
initInternal();
// 触发 INITIALIZED 事件的监听器
setStateInternal(LifecycleState.INITIALIZED, null, false);
} catch (Throwable t) {
}
}
Tomcat 自定义了一些监听器,这些监听器是父组件在创建子组件的过程中注册到子组件的。比如 MemoryLeakTrackingListener 监听器,用来检测 Context 容器中的内存泄漏,这个监听器是 Host 容器在创建 Context 容器时注册到 Context 中的。我们还可以在 server.xml 中定义自己的监听器,Tomcat 在启动时会解析 server.xml,创建监听器并注册到容器组件。
整体类图:
二、 Tomcat启动流程
通常我通过执行tomcat bin下的 startup.sh 脚本启动tomcat,那么tomcat到底是如何启动的呢? 具体流程如下:
2.1 Catalina 组件
它是个启动类,通过解析server.xml ,创建相应的组件,并调用server的start方法,向下传递启动。Catalina是一个管理则者的身份,它还需要处理各种异常场景,当发生 ctrl+ c 强制关闭时,是如何释放资源的。Catalina在JVM中注册了一个关闭的钩子。主要任务就是创建Server
public void start() {
if (getServer() == null) {
load();
}
if (getServer() == null) {
log.fatal("Cannot start server. Server instance is not configured.");
return;
}
long t1 = System.nanoTime();
// Start the new server
try {
getServer().start();
} catch (LifecycleException e) {
return;
}
// Register shutdown hook
if (useShutdownHook) {
if (shutdownHook == null) {
shutdownHook = new CatalinaShutdownHook();
}
// 注册一个jvm的回调函数;内部其实是进行资源的释放和清理
Runtime.getRuntime().addShutdownHook(shutdownHook);
}
// 监听停止请求
if (await) {
await();
stop();
}
}
2.2 Server 组件
Server的具体实现类是StandServer.这个组件会管理 service的生命周期。在server内部维护着多个service组件。还有一个重要的任务就是,启动Socket来监听停止端口。
// 启动 Service 组件
if (getState().isAvailable()) {
try {
service.start();
} catch (LifecycleException e) {
// Ignore
}
}
2.3 Service 组件
Service组件的具体实现类是StandardService,
/**
*
* 这是service 实例
*
*/
private Server server = null;
/**
*
* 连接器
*/
protected Connector connectors[] = new Connector[0];
private final Object connectorsLock = new Object();
/**
* engine容器
*
*/
private Engine engine = null;
@Override
protected void startInternal() throws LifecycleException {
// 1、触发启动监听器
setState(LifecycleState.STARTING);
// 2、启动引擎
if (engine != null) {
synchronized (engine) {
engine.start();
}
}
// 3、mapper监听器 热加载部署
mapperListener.start();
// 4、连接器的启动 内部会启动子组建 如:endoint组件
synchronized (connectorsLock) {
for (Connector connector: connectors) {
connector.start();
}
}
}
}
service作为管理者,最重要的是维护其他组件的生命周期;启动组件时要维护依赖关系。
2.4 Engine组件
engine组件的本质是一个容器,它继承了ContainerBase基类,并实现了Engine接口
public class StandardEngine extends ContainerBase implements Engine {
}
参考
极客时间-深入理解Tomcat