Tomcat启动过程源码分析五

前言

上一篇文章中我们讨论了Bootstrap类中main方法中涉及到的load方法,今天这篇文章我们来查看下start方法。

/**
* Start the Catalina daemon.
*/
public void start()
throws Exception {
if( catalinaDaemon==null ) init();

Method method = catalinaDaemon.getClass().getMethod("start", (Class [] )null);
method.invoke(catalinaDaemon, (Object [])null);

}

具体代码就不分析了,可以看出start方法使用了反射调用了catalinaDaemonstart方法,而catalinaDeamon是类Catalina的实例,直接查看Catalina类的start方法

Catalina类
/**
* Start a new server instance.
*/
public void start() {
//...判断代码
// Start the new server
try {
//11111
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;
}

long t2 = System.nanoTime();
if(log.isInfoEnabled()) {
log.info("Server startup in " + ((t2 - t1) / 1000000) + " ms");
}

//22222222
// Register shutdown hook
if (useShutdownHook) {
if (shutdownHook == null) {
shutdownHook = new CatalinaShutdownHook();
}
Runtime.getRuntime().addShutdownHook(shutdownHook);

// If JULI is being used, disable JULI's shutdown hook since
// shutdown hooks run in parallel and log messages may be lost
// if JULI's hook completes before the CatalinaShutdownHook()
LogManager logManager = LogManager.getLogManager();
if (logManager instanceof ClassLoaderLogManager) {
((ClassLoaderLogManager) logManager).setUseShutdownHook(
false);
}
}
//333333333333
if (await) {
await();
stop();
}
}

可以看出来除了一些判断意外,start方法基本分成了3个步骤,我们依次来查看。

第一步

在第一步调用了getServer().start()方法,其实也就是调用了StandardServerstart方法,我们查看StandardServer类发现,他并没有start方法,继续查看其父类,发现其父类包含了LifecycleBase,其中实现了start方法,而在start方法中又调用了startInternal方法,所以看到这里大概也明白了,start这个方法类似init方法,也使用了模版设计模式,所以我们直接看StandardServer类的startInternal方法就可以了。

@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();
}
}
}

除了调用了globalNamingResourcesstart方法,还调用了本身Servicestart方法,由于globalNamingResources是一个组件,我们这里暂时不介绍,有兴趣可以自己跟源码查看,我们来看下servicestart方法, 也就是StandardServicestartInternal方法。

@Override
protected void startInternal() throws LifecycleException {

if(log.isInfoEnabled())
log.info(sm.getString("standardService.start.name", this.name));
setState(LifecycleState.STARTING);

// Start our defined Container first
if (container != null) {
//11111
synchronized (container) {
container.start();
}
}

synchronized (executors) {
for (Executor executor: executors) {
executor.start();
}
}

// Start our defined Connectors second
synchronized (connectorsLock) {
for (Connector connector: connectors) {
try {
//222222
// If it has already failed, don't try and start it
if (connector.getState() != LifecycleState.FAILED) {
connector.start();
}
} catch (Exception e) {
log.error(sm.getString(
"standardService.connector.startFailed",
connector), e);
}
}
}
}

可以看到StandardServicestartInternal方法主要做了2个动作,第一个是调用了Containerstart方法,第二个是调用了Connectorstart方法,我们先看Containerstart方法,也就是对应实现类StandardEnginestartInternal方法。

@Override
protected synchronized void startInternal() throws LifecycleException {

// Log our server identification information
if(log.isInfoEnabled())
log.info( "Starting Servlet Engine: " + ServerInfo.getServerInfo());

// Standard container startup
super.startInternal();
}

查看类继承关系

public class StandardEngine extends ContainerBase implements Engine

查看类ContainerBase中的startInternal方法

@Override
protected synchronized void startInternal() throws LifecycleException {

//启动各种组件
// Start our subordinate components, if any
if ((loader != null) && (loader instanceof Lifecycle))
((Lifecycle) loader).start();
logger = null;
getLogger();
if ((manager != null) && (manager instanceof Lifecycle))
((Lifecycle) manager).start();
if ((cluster != null) && (cluster instanceof Lifecycle))
((Lifecycle) cluster).start();
Realm realm = getRealmInternal();
if ((realm != null) && (realm instanceof Lifecycle))
((Lifecycle) realm).start();
if ((resources != null) && (resources instanceof Lifecycle))
((Lifecycle) resources).start();

//获取子容器,启动所有的子容器
//子容器主要是 Host 对应实现类 StandardHost 调用其startInternal方法
// Start our child containers, if any
Container children[] = findChildren();
List<Future> results = new ArrayList<Future>();
for (int i = 0; i < children.length; i++) {
results.add(startStopExecutor.submit(new StartChild(children[i])));
}

boolean fail = false;
for (Future result : results) {
try {
result.get();
} catch (Exception e) {
log.error(sm.getString("containerBase.threadedStartFailed"), e);
fail = true;
}

}
if (fail) {
throw new LifecycleException(
sm.getString("containerBase.threadedStartFailed"));
}
//启动pipeline 组件
// Start the Valves in our pipeline (including the basic), if any
if (pipeline instanceof Lifecycle)
((Lifecycle) pipeline).start();

setState(LifecycleState.STARTING);
//启动container 后台线程
// Start our thread
threadStart();

}

从代码的注释中可以清楚的看到StandardEnginestartInternal方法都做了什么,我们继续查看ConnectorstartInternal方法。

@Override
protected void startInternal() throws LifecycleException {

// Validate settings before starting
if (getPort() < 0) {
throw new LifecycleException(sm.getString(
"coyoteConnector.invalidPort", Integer.valueOf(getPort())));
}

setState(LifecycleState.STARTING);

try {
//11
protocolHandler.start();
} catch (Exception e) {
String errPrefix = "";
if(this.service != null) {
errPrefix += "service.getName(): "" + this.service.getName() + ""; ";
}

throw new LifecycleException
(errPrefix + " " + sm.getString
("coyoteConnector.protocolHandlerStartFailed"), e);
}
//2
mapperListener.start();
}

我们可以看到ConnectorstartInternal方法主要做了两件事,第一件是调用了变量protocolHandlerstart方法,第二件事是调用了mapperListenerstart方法,我们主要看下protocolHandler的调用。

类似init方法讲解中提到的,protocolHandler有两个实例分别代表http请求和ajb请求,我们主要看对应http请求,也就是实例Http11ProtocolstartInternal方法。我们查看类Http11Protocol发现其中并无start方法相关,查看其父类AbstractProtocol发现其中的start方法。

@Override
public void start() throws Exception {
if (getLog().isInfoEnabled())
getLog().info(sm.getString("abstractProtocolHandler.start",
getName()));
try {
endpoint.start();
} catch (Exception ex) {
getLog().error(sm.getString("abstractProtocolHandler.startError",
getName()), ex);
throw ex;
}
}

其中调用了endpointstart方法。而在Http11Protocol类的构造方法中可以看到

public Http11Protocol() {
endpoint = new JIoEndpoint();
cHandler = new Http11ConnectionHandler(this);
((JIoEndpoint) endpoint).setHandler(cHandler);
setSoLinger(Constants.DEFAULT_CONNECTION_LINGER);
setSoTimeout(Constants.DEFAULT_CONNECTION_TIMEOUT);
setTcpNoDelay(Constants.DEFAULT_TCP_NO_DELAY);
}

endpoint是类JIoEndpoint的实例,我们继续查看JIoEndpoint

@Override
public void startInternal() throws Exception {

if (!running) {
running = true;
paused = false;

// Create worker collection
if (getExecutor() == null) {
createExecutor();
}

initializeConnectionLatch();

startAcceptorThreads();

// Start async timeout thread
Thread timeoutThread = new Thread(new AsyncTimeout(),
getName() + "-AsyncTimeout");
timeoutThread.setPriority(threadPriority);
timeoutThread.setDaemon(true);
timeoutThread.start();
}
}

看到这里Connectorstart方法就结束了,StandardServicestart方法也结束了。

在文章的最开始我们提到了Catalina类的start方法,上面跟源码分析了那么多其实一直是分析getServer().start(),下一篇文章我们继续分析Catalina类的start方法的剩余部分。

posted @ 2016-06-30 23:43  coldridgeValley  阅读(1336)  评论(0)    收藏  举报