前言
上篇文章分析了Tomcat的 Catalina 类,这个类的主要作用就是根据 server.xml 的配置来初始化 Tomcat 运行所需要的组件,比如 Server,Service 等等,然后调用成员变脸 Server 类对象的的 init 和 start 方法,来启动 tomcat。
一个 Server 类的实例就代表了一个 Tomcat 的容器,一个Tomcat 进程只会有一个 Server 实例。Server 是一个接口,它的实现类是 StandardServer
1 Server#init 方法
StandardServer 继承自 LifecycleMBeanBase, 而 LifecycleMBeanBase 继承自 LifecycleBase,LifecycleBase 实现了 Lifecycle 接口,Lifecycle 定义了组件生命周期的方法,其中就包含 init(), start(), stop() 等方法。
下面看 StandardServer 的 init() 方法也就是父类LifecycleBase 的 init()
1.1 LifecycleBase#init 方法
@Override
public final synchronized void init() throws LifecycleException {
if (!state.equals(LifecycleState.NEW)) {
invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
}
try {
setStateInternal(LifecycleState.INITIALIZING, null, false);
initInternal();
setStateInternal(LifecycleState.INITIALIZED, null, false);
} catch (Throwable t) {
handleSubClassException(t, "lifecycleBase.initFail", toString());
}
}
/**
* Sub-classes implement this method to perform any instance initialisation
* required.
*
* @throws LifecycleException If the initialisation fails
*/
protected abstract void initInternal() throws LifecycleException;
LifecycleBase 对 init 方法做了一个抽象,使用模板方法模式,提供 initInternal() 方法给子类实现。
init 方法里首先判断 state 属性是不是为 LifecycleState.NEW,
state 是 LifecycleBase 的一个属性,其声明为
/**
* The current state of the source component.
*/
private volatile LifecycleState state = LifecycleState.NEW;
它的作用是用来标识当前组件的状态。
Tomcat 里很多组件都是有状态的,包括 Server,Container 等,其实 Tomcat 里只要有生命周期的组件,都会继承自 LifecycleBase。
判断完之后分别在 initInternal() 方法调用前后,调用 setStateInternal 方法将 state 的值设置成 INITIALIZING 和 INITIALIZED。
private synchronized void setStateInternal(LifecycleState state, Object data, boolean check)
throws LifecycleException {
if (log.isDebugEnabled()) {
log.debug(sm.getString("lifecycleBase.setState", this, state));
}
if (check) {
// Must have been triggered by one of the abstract methods (assume
// code in this class is correct)
// null is never a valid state
if (state == null) {
invalidTransition("null");
// Unreachable code - here to stop eclipse complaining about
// a possible NPE further down the method
return;
}
// Any method can transition to failed
// startInternal() permits STARTING_PREP to STARTING
// stopInternal() permits STOPPING_PREP to STOPPING and FAILED to
// STOPPING
if (!(state == LifecycleState.FAILED ||
(this.state == LifecycleState.STARTING_PREP &&
state == LifecycleState.STARTING) ||
(this.state == LifecycleState.STOPPING_PREP &&
state == LifecycleState.STOPPING) ||
(this.state == LifecycleState.FAILED &&
state == LifecycleState.STOPPING))) {
// No other transition permitted
invalidTransition(state.name());
}
}
this.state = state;
String lifecycleEvent = state.getLifecycleEvent();
if (lifecycleEvent != null) {
fireLifecycleEvent(lifecycleEvent, data);
}
}
设置完 state 的状态之后,就触发该状态的事件了,通知事件监听器
/**
* The list of registered LifecycleListeners for event notifications.
*/
private final List<LifecycleListener> lifecycleListeners = new CopyOnWriteArrayList<>();
protected void fireLifecycleEvent(String type, Object data) {
LifecycleEvent event = new LifecycleEvent(this, type, data);
for (LifecycleListener listener : lifecycleListeners) {
listener.lifecycleEvent(event);
}
}
这里的 LifecycleListener 对象是在 Catalina 对象解析 server.xml 文件时就已经创建好并加到 lifecycleListeners 里的。这个不是特别重要就不细讲了。
1.2 LifecycleMBeanBase#initInternal 方法
private ObjectName oname = null;
protected MBeanServer mserver = null;
protected void initInternal() throws LifecycleException {
// If oname is not null then registration has already happened via
// preRegister().
if (oname == null) {
mserver = Registry.getRegistry(null, null).getMBeanServer();
oname = register(this, getObjectNameKeyProperties());
}
}
LifecycleMBeanBase 的 initInternal 方法也很简单,就是初始化 ObjectName 类型的 oname 属性,和 MBeanServer 的 mserver 属性你,并注册 oname 到 mserver,这两操作是基于 Tomcat 的安全性和隔离性的。有兴趣的话可以自行去了解一下 java 的 MBeanServer 相关知识,这里就不细讲了。接着往下看 StandardServer 的 initInternal 方法
1.3 StandardServer#initInternal 方法
/**
* Invoke a pre-startup initialization. This is used to allow connectors
* to bind to restricted ports under Unix operating environments.
*/
@Override
protected void initInternal() throws LifecycleException {
super.initInternal();
// Initialize utility executor
reconfigureUtilityExecutor(getUtilityThreadsInternal(utilityThreads));
register(utilityExecutor, "type=UtilityExecutor");
// Register global String cache
// Note although the cache is global, if there are multiple Servers
// present in the JVM (may happen when embedding) then the same cache
// will be registered under multiple names
onameStringCache = register(new StringCache(), "type=StringCache");
// Register the MBeanFactory
MBeanFactory factory = new MBeanFactory();
factory.setContainer(this);
onameMBeanFactory = register(factory, "type=MBeanFactory");
// Register the naming resources
globalNamingResources.init();
// Populate the extension validator with JARs from common and shared
// class loaders
if (getCatalina() != null) {
ClassLoader cl = getCatalina().getParentClassLoader();
// Walk the class loader hierarchy. Stop at the system class loader.
// This will add the shared (if present) and common class loaders
while (cl != null && cl != ClassLoader.getSystemClassLoader()) {
if (cl instanceof URLClassLoader) {
URL[] urls = ((URLClassLoader) cl).getURLs();
for (URL url : urls) {
if (url.getProtocol().equals("file")) {
try {
File f = new File (url.toURI());
if (f.isFile() &&
f.getName().endsWith(".jar")) {
ExtensionValidator.addSystemResource(f);
}
} catch (URISyntaxException e) {
// Ignore
} catch (IOException e) {
// Ignore
}
}
}
}
cl = cl.getParent();
}
}
// Initialize our defined Services
for (int i = 0; i < services.length; i++) {
services[i].init();
}
}
整个方法可以分为三段,分别是 if 块之前、if 块、和 if 块之后的 for 循环。
1.2.1 第一段
第一段代码的第一行,调用了 super.initInternal() 方法,也就是调用了 LifecycleMBeanBase#initInternal 方法。然后调用
reconfigureUtilityExecutor 方法初始化了 utilityExecutor 属性和 utilityExecutorWrapper 属性
/**
* Utility executor with scheduling capabilities.
*/
private ScheduledThreadPoolExecutor utilityExecutor = null;
/**
* Utility executor wrapper.
*/
private ScheduledExecutorService utilityExecutorWrapper = null;
其中 utilityExecutorWrapper 是对 utilityExecutor 的包装。utilityExecutorWrapper 这个线程池是用来执行一些特殊任务的,比如状态检查等,关于这个线程池的用处,后面的文章会提到,这里先略过。然后初始化 onameMBeanFactory 和 onameStringCache 两个 ObjectName 类型的属性,就是注册 StringCache 对象和 MBeanFactory 对象到 MBeanServer 。
最后一行就是调用 globalNamingResources 对象的 init 方法,globalNamingResources 对象是在 StandardServer 类的构造方法里初始化的。
/**
* Global naming resources.
*/
private NamingResourcesImpl globalNamingResources = null;
globalNamingResources 是 tomcat 支持的一个比较重要的特性,本篇文章暂时不进行深入的解析。
1.2.2 第二段
第二段的 if 代码块,是将 catalina 的 parentClassLoader (这个属性在 Bootstrap#init 方法里通过反射调用 Catalina 的 setParentClassLoader 将 sharedClassLoader 传进去,也就说,这个 parentClassLoader 就是 sharedClassLoader 指向的对象,也就是一个 URLClassLoader 对象)里能加载的 jar 文件里的 manifest ,都添加到一个集合里(ExtensionValidator 的一个 ArrayList 里)
1.2.3 第三段
第三段代码是循环调用 Server 类的属性 services 数组的元的 init 方法
/**
* The set of Services associated with this Server.
*/
private Service services[] = new Service[0];
Server 里的 service 是在 server.xml 里定义的,在 Catalina 解析 server.xml 的时候初始化,并注入到 Server 对象里。
显然 StandardServer#initInternal() 方法最重要的就是第三段,调用 Service#init 方法。Service 是 Tomcat 的核心组件之一。
2 Server#start 方法
start 方法跟 init 方法类似,分为 LifecycleBase#start 和 StandardServer#startInternal 方法。
2.1 LifecycleBase#start 方法
public final synchronized void start() throws LifecycleException {
if (LifecycleState.STARTING_PREP.equals(state) || LifecycleState.STARTING.equals(state) ||
LifecycleState.STARTED.equals(state)) {
if (log.isDebugEnabled()) {
Exception e = new LifecycleException();
log.debug(sm.getString("lifecycleBase.alreadyStarted", toString()), e);
} else if (log.isInfoEnabled()) {
log.info(sm.getString("lifecycleBase.alreadyStarted", toString()));
}
return;
}
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);
}
try {
setStateInternal(LifecycleState.STARTING_PREP, null, false);
startInternal();
if (state.equals(LifecycleState.FAILED)) {
// This is a 'controlled' failure. The component put itself into the
// FAILED state so call stop() to complete the clean-up.
stop();
} else if (!state.equals(LifecycleState.STARTING)) {
// Shouldn't be necessary but acts as a check that sub-classes are
// doing what they are supposed to.
invalidTransition(Lifecycle.AFTER_START_EVENT);
} else {
setStateInternal(LifecycleState.STARTED, null, false);
}
} catch (Throwable t) {
// This is an 'uncontrolled' failure so put the component into the
// FAILED state and throw an exception.
handleSubClassException(t, "lifecycleBase.startFail", toString());
}
}
start 方法逻辑很简单,先做一些 state 状态校验,确保是可以当前组价出在可启动的状态。然后就调用 startInternal 方法,启动完成之后就把 state 设置成 LifecycleState.STARTED 状态。
2.2 StandardServer#startInternal 方法
/**
* Start nested components ({@link Service}s) and implement the requirements
* of {@link org.apache.catalina.util.LifecycleBase#startInternal()}.
*
* @exception LifecycleException if this component detects a fatal error
* that prevents this component from being used
*/
@Override
protected void startInternal() throws LifecycleException {
fireLifecycleEvent(CONFIGURE_START_EVENT, null);
setState(LifecycleState.STARTING);
globalNamingResources.start();
// Start our defined Services
synchronized (servicesLock) {
for (int i = 0; i < services.length; i++) {
services[i].start();
}
}
if (periodicEventDelay > 0) {
monitorFuture = getUtilityExecutor().scheduleWithFixedDelay(
new Runnable() {
@Override
public void run() {
startPeriodicLifecycleEvent();
}
}, 0, 60, TimeUnit.SECONDS);
}
}
protected void startPeriodicLifecycleEvent() {
if (periodicLifecycleEventFuture == null || (periodicLifecycleEventFuture != null && periodicLifecycleEventFuture.isDone())) {
if (periodicLifecycleEventFuture != null && periodicLifecycleEventFuture.isDone()) {
// There was an error executing the scheduled task, get it and log it
try {
periodicLifecycleEventFuture.get();
} catch (InterruptedException | ExecutionException e) {
log.error(sm.getString("standardServer.periodicEventError"), e);
}
}
periodicLifecycleEventFuture = getUtilityExecutor().scheduleAtFixedRate(
new Runnable() {
@Override
public void run() {
fireLifecycleEvent(Lifecycle.PERIODIC_EVENT, null);
}
}, periodicEventDelay, periodicEventDelay, TimeUnit.SECONDS);
}
}
方法的第一行代码先触发 CONFIGURE_START_EVENT 事件,以便执行 StandardServer 的 LifecycleListener 监听器,然后调用 setState 方法设置成 LifecycleBase 的 state 属性为 LifecycleState.STARTING。
接着就 globalNamingResources.start(),跟 initInternal 方法其实是类似的。
再接着就调用 Service 的 start 方法来启动 Service 组件。可以看出,StandardServe 的 startInternal 跟 initInternal 方法类似,都是调用内部的 service 组件的相关方法。
调用完 service.init 方法后,就使用 getUtilityExecutor() 返回的线程池延迟执行startPeriodicLifecycleEvent 方法,而在 startPeriodicLifecycleEvent 方法里,也是使用 getUtilityExecutor() 方法,定期执行 fireLifecycleEvent 方法,处理 Lifecycle.PERIODIC_EVENT 事件,如果有需要定期处理的,可以再 Server 的 LifecycleListener 里处理 Lifecycle.PERIODIC_EVENT 事件。
3. Lifecycle 的状态流转
Tomcat 给各个组件定义了一些生命周期中的状态,在枚举类 LifecycleState 里
public enum LifecycleState {
NEW(false, null),
INITIALIZING(false, Lifecycle.BEFORE_INIT_EVENT),
INITIALIZED(false, Lifecycle.AFTER_INIT_EVENT),
STARTING_PREP(false, Lifecycle.BEFORE_START_EVENT),
STARTING(true, Lifecycle.START_EVENT),
STARTED(true, Lifecycle.AFTER_START_EVENT),
STOPPING_PREP(true, Lifecycle.BEFORE_STOP_EVENT),
STOPPING(false, Lifecycle.STOP_EVENT),
STOPPED(false, Lifecycle.AFTER_STOP_EVENT),
DESTROYING(false, Lifecycle.BEFORE_DESTROY_EVENT),
DESTROYED(false, Lifecycle.AFTER_DESTROY_EVENT),
FAILED(false, null);
private final boolean available;
private final String lifecycleEvent;
private LifecycleState(boolean available, String lifecycleEvent) {
this.available = available;
this.lifecycleEvent = lifecycleEvent;
}
……
}
这些状态的流转如下图
小结
本篇文章介绍了 Server 组件,Server 组件是 tomcat 的核心组件之一,它是通过调用 init 和 start 方法来启动 tomcat 的,而 Server 的 init 方法和 start 方法则是调用 Service 的 init 和 start 方法来启动 Service(tomcat的另一个核心组件)。
看一看出,一个 Tomcat 进程只有一个 Server 实例,一个 Server 实例可以包含多个 Service 对象。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。