Tomcat的Start过程有两条主线,第一条启动Container组件,另一条启动Connector组件。
public void start() throws LifecycleException {
。
。
。
略
lifecycle.fireLifecycleEvent(START_EVENT, null);
started = true;
// Start our defined Container first
//启动容器
if (container != null) {
synchronized (container) {
if (container instanceof Lifecycle) {
((Lifecycle) container).start();
}
}
}
// Start our defined Connectors second
//启动连接器
synchronized (connectors) {
for (int i = 0; i < connectors.length; i++) {
try {
((Lifecycle) connectors[i]).start();
} catch (Exception e) {
log.error(sm.getString(
"standardService.connector.startFailed",
connectors[i]), e);
}
}
}
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
}
首先看看启动Container容器部分的源码。
最先启动的容器是Engine,在StandardEngine类的start方法中进行一系列的JMX服务注册之后,接着会调用父类ContainerBase的start方法。
public synchronized void start() throws LifecycleException {
略
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);
started = true;
略
// Start our child containers, if any
Container children[] = findChildren();
for (int i = 0; i < children.length; i++) {
if (children[i] instanceof Lifecycle)
((Lifecycle) children[i]).start();
}
// Start the Valves in our pipeline (including the basic), if any
if (pipeline instanceof Lifecycle)
((Lifecycle) pipeline).start();
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(START_EVENT, null);
// Start our thread
threadStart();
// Notify our interested LifecycleListeners
lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);
}
在start方法中会触发三个事件,分别是before_start,start,after_start。既然有事件产生,那么就应该有处理事件的监听器。Engine容器的监听器是EngineConfig类,EngineConfig实现了LifecycleListener接口,因此事件的处理逻辑在lifecycleEvent方法中。在EngineConfig的lifecycleEvent方法中处理事件的逻辑比较简单,只是记录一下操作日志,因此Engine容器启动产生的几个事件可以不用太关注。Engine容器启动过程中会找出它所有的Host子类,并且调用Host对应的start方法启动Host容器。除了启动Host容器,还会启动一个线程执行后台处理任务,线程的run方法中会周期性的调用processChildren方法,而processChildren方法会调用自身对象backgroundProcess方法和每个子容器的processChildren方法。在backgroundProcess方法中会检查类的时间戳,Session对象的超时时间和执行Context容器的reload等操作。而reload操作的实质是先停止其子容器,然后再启动,只不过这个操作是由程序自动发起而不是由用户产生的。