Tomcat 基本接口
- Tomcat 中最顶层的容器叫Server,代表整个服务器,Server中包含至少一个Service
- Service 主要有 Connector和Container组成
- Connector负责网络连接,request/response的创建等
- Container负责具体的Servlet处理
- 一个Server可以包含多个Service(多个Application),一个Service只有一个Container,但可以有多个Connector
- Tomcat中的Server由Catalina来管理,Catalina管理Tomcat的生命周期

入口
Bootstrap是Tomcat的入口(main函数在这里)
public static void main(String args[]) {
if (daemon == null) {
Bootstrap bootstrap = new Bootstrap();
try {
//初始化ClassLoader,并且使用ClassLoader创建Catalina实例,然后
//赋值给catalinaDaemon
bootstrap.init();
} catch (Throwable t) {
handleThrowable(t);
t.printStackTrace();
return;
}
daemon = bootstrap;
} else {
Thread.currentThread().setContextClassLoader(daemon.catalinaLoader);
}
try {
String command = "start";
if (args.length > 0) {
command = args[args.length - 1];
}
/*daemon的load(),start(),setAwait()等方
法都是利用反射调用Catalina中的方法*/
if (command.equals("startd")) {
args[args.length - 1] = "start";
daemon.load(args);
daemon.start();
} else if (command.equals("stopd")) {
args[args.length - 1] = "stop";
daemon.stop();
} else if (command.equals("start")) {
daemon.setAwait(true);
daemon.load(args);
daemon.start();
} else if (command.equals("stop")) {
daemon.stopServer(args);
} else if (command.equals("configtest")) {
daemon.load(args);
if (null==daemon.getServer()) {
System.exit(1);
}
System.exit(0);
} else {
log.warn("Bootstrap: command \"" + command + "\" does not exist.");
}
} catch (Throwable t) {
// Unwrap the Exception for clearer error reporting
if (t instanceof InvocationTargetException &&
t.getCause() != null) {
t = t.getCause();
}
handleThrowable(t);
t.printStackTrace();
System.exit(1);
}
}
Catalina的启动过程
从上面的代码中看出,Tomcat启动代码
daemon.setAwait(true);
daemon.load(args);
daemon.start();
分别对应的Catalina的setAwait(),load(),start()方法。
- Catalina的setAwait()的方法通过设置一个标志位,在服务器启动的时候是否进入等待状态
- load()是读取相关的配置文件
- start()主要的功能是启动Server,调用Server的start()
public void start() {
...
try {
//调用Server的start()方法
getServer().start();
} catch (LifecycleException e) {
log.fatal(sm.getString("catalina.serverStartFail"), e);
try {
getServer().destroy();
} catch (LifecycleException e1) {
log.debug("destroy() failed for failed Server ", e1);
}
return;
}
...
//通过setAwait(),设置await = true
if (await) {
await();
stop();
}
}
Server的启动
Catalina的启动,其实是调用Server的Start()方法,Server的默认实现是StartardServer。
继承关系:
StartardServer ==> LifecycleMBeanBase ==>LifecycleBase==>Lifecycle
start()方法是在LifecycleBase中
@Override
public final synchronized void start() throws LifecycleException {
...
if (state.equals(LifecycleState.NEW)) {
init();
} else if (state.equals(LifecycleState.FAILED)) {
stop();
} else if (!state.equals(LifecycleState.INITIALIZED) &&
!state.equals(LifecycleState.STOPPED)) {
invalidTransition(Lifecycle.BEFORE_START_EVENT);
}
...
setStateInternal(LifecycleState.STARTING_PREP, null, false);
startInternal();
...
}
这个类是一个模板类,在init() 中调用了initInternal(),然后启动的时候调用startInternal(),而这2个方法是在StartardServer中实现。有点类似Spring的AbstractApplicationContext. 然后看一下StardardServer中的initInternal()和startInternal()方法,其实这2个方法就是对自己的Service进行初始化和启动
protected void initInternal() throws LifecycleException {
super.initInternal();
...
// Initialize our defined Services
for (int i = 0; i < services.length; i++) {
services[i].init();
}
}
@Override
protected void startInternal() throws LifecycleException {
// Start our defined Services
synchronized (servicesLock) {
for (int i = 0; i < services.length; i++) {
services[i].start();
}
}
}
在Catalina启动的后,还有一个await()的方法,也是调用StandardServer的await()方法,改方法的主要作为就是
@Override
public void await() {
if( port == -2 ) {
return;
}
if( port==-1 ) {
try {
awaitThread = Thread.currentThread();
while(!stopAwait) {
try {
Thread.sleep( 10000 );
} catch( InterruptedException ex ) {
}
}
} finally {
awaitThread = null;
}
return;
}
...
awaitSocket = new ServerSocket(port, 1,
InetAddress.getByName(address));
···
boolean match = command.toString().equals(shutdown);
if (match) {
log.info(sm.getString("standardServer.shutdownViaPort"));
break;
} else
log.warn("StandardServer.await: Invalid command '"
+ command.toString() + "' received");
当为-1和-2的时候进行特殊处理,否则监听端口(默认8005),如果收到"SHUTDOWN"消息则关闭Tomcat
Service启动
Service的默认实现是StandardService,同时StandardService也继承自LifecycleMBeanBase(嗯,和StandardServer一样的生命周期管理)
@Override
protected void startInternal() throws LifecycleException {
...
// Start our defined Container first
if (container != null) {
synchronized (container) {
container.start();
}
}
synchronized (executors) {
for (Executor executor: executors) {
executor.start();
}
}
mapperListener.start();
// Start our defined Connectors second
synchronized (connectorsLock) {
for (Connector connector: connectors) {
if (connector.getState() != LifecycleState.FAILED) {
connector.start();
}
}
}
}
initInternal()的方式和startInternal()的方式差不多,也是调用Container、executors、mapperListener、connector的init()的方法。
- container和connector前面说过
- mapperListener Mapper的监听器,可以监听container容器的变化
- executors是在connectors中管理线程的线程池,在serverx.xml的配置中默认是注释掉的
可以看出tomcat的启动顺序如下图

Lifecycle
Lifecycle是tomcat用于生命周期管理的接口

Lifecycle总共有13常量,用于区别13中事件,默认的实现是LifecycleBase。原理应该比较好理解,当一些事件触发的时候,会触发类去执行相对应的操作(例如 start的时候,会根据事件到底执行init()还是stop())。
为了方便扩展,我们还可以注册LifecycleListener,把这些监听器加入(addLifecycleListnener方法)监听,当事件触发的时候,同时还会触发这些监听器对应的处理。(spring boot中在启动的时候也用到相同方法),Lifecycle的注释中说明了哪些事件会调用哪些方法
* start()
* -----------------------------
* | |
* | init() |
* NEW -»-- INITIALIZING |
* | | | | ------------------«-----------------------
* | | |auto | | |
* | | \|/ start() \|/ \|/ auto auto stop() |
* | | INITIALIZED --»-- STARTING_PREP --»- STARTING --»- STARTED --»--- |
* | | | | |
* | |destroy()| | |
* | --»-----«-- ------------------------«-------------------------------- ^
* | | | |
* | | \|/ auto auto start() |
* | | STOPPING_PREP ----»---- STOPPING ------»----- STOPPED -----»-----
* | \|/ ^ | ^
* | | stop() | | |
* | | -------------------------- | |
* | | | | |
* | | | destroy() destroy() | |
* | | FAILED ----»------ DESTROYING ---«----------------- |
* | | ^ | |
* | | destroy() | |auto |
* | --------»----------------- \|/ |
* | DESTROYED |
* | |
* | stop() |
* ----»-----------------------------»------------------------------
*
本文详细解析了Tomcat服务器的启动流程,从Bootstrap入口开始,深入介绍了Server、Service、Connector和Container的初始化与启动过程,以及Catalina的生命周期管理。
674

被折叠的 条评论
为什么被折叠?



