共计 6481 个字符,预计需要花费 17 分钟才能阅读完成。
上一篇咱们看了 Tomcat
中各个组件的 init
过程,初始化赋值好了,那么接下来就该轮到 start
了,话不多说,马上进入主题~
1. Bootstrap.start()
通过 start
办法咱们能够看到他是通过反射调用了 Catalina.start()
办法,按 F7 跳到这个类外面看一下。
public void start() throws Exception {if (catalinaDaemon == null) {init();
}
// 通过反射调用 Catalina.start() 办法
Method method = catalinaDaemon.getClass().getMethod("start", (Class [])null);
method.invoke(catalinaDaemon, (Object [])null);
}
2. Catalina.start()
进来一看,又是相熟的套娃格调,还得持续往里面跳转
3. LifecycleBase.start()
还是这个相熟的组件生命周期类,看到这里就好像看到了终局,必定是跟 initInternal
这个办法一样一层层嵌套进去,让咱们走起~
4. StandardServer.startInternal()
之前咱们有所过在一个 Tomcat
中是能够有多个 service
的,所以这里须要遍历所有的 service
别离让各自启动起来
在 server.xml
文件中再给他配置一个 <Service>
标签即可,如图所示:
5. StandardService.startInternal()
开始进入正题了,在这个办法中咱们能够看到它别离做了以下操作:
- 容器的启动:
engine.start()
- 连接器的启动:
connector.start()
protected void startInternal() throws LifecycleException {if(log.isInfoEnabled())
log.info(sm.getString("standardService.start.name", this.name));
setState(LifecycleState.STARTING);
// 这里首先启动咱们定义的容器 engine
if (engine != null) {synchronized (engine) {
// 启动 engine 子容器
engine.start();}
}
synchronized (executors) {for (Executor executor: executors) {executor.start();
}
}
mapperListener.start();
// Start our defined Connectors second
synchronized (connectorsLock) {for (Connector connector: connectors) {
try {
// 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);
}
}
}
}
6. StandardEngine.startInternal()
这里间接调用的 ContainerBase.startInternal
办法实现上司组件的启动
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();}
7. ContainerBase.startInternal()
这里应用的是线程池的形式,如果有多个 Host
,那么就能够多个线程并行实例化Host
,放慢Tomcat
启动速度
protected synchronized void startInternal() throws LifecycleException {
// 启动上司容器
logger = null;
getLogger();
Cluster cluster = getClusterInternal();
if (cluster instanceof Lifecycle) {((Lifecycle) cluster).start();}
Realm realm = getRealmInternal();
if (realm instanceof Lifecycle) {((Lifecycle) realm).start();}
// 查找并启动子容器,Host 在初始化阶段后还是不残缺的,须要持续封装,把容器关系保护残缺
Container children[] = findChildren();
List<Future<Void>> results = new ArrayList<>();
for (Container child : children) {results.add(startStopExecutor.submit(new StartChild(child)));
}
MultiThrowable multiThrowable = null;
for (Future<Void> result : results) {
try {result.get();
} catch (Throwable e) {log.error(sm.getString("containerBase.threadedStartFailed"), e);
if (multiThrowable == null) {multiThrowable = new MultiThrowable();
}
multiThrowable.add(e);
}
}
if (multiThrowable != null) {throw new LifecycleException(sm.getString("containerBase.threadedStartFailed"),
multiThrowable.getThrowable());
}
// Start the Valves in our pipeline (including the basic), if any
if (pipeline instanceof Lifecycle) {((Lifecycle) pipeline).start();}
// 设置容器生命周期状态
setState(LifecycleState.STARTING);
// Start our thread
threadStart();}
[图片上传失败 …(image-bc6c2d-1616772543941)]
8. StandardHost.startInternal()
protected synchronized void startInternal() throws LifecycleException {
// Set error report valve
String errorValve = getErrorReportValveClass();
if ((errorValve != null) && (!errorValve.equals(""))) {
try {
boolean found = false;
Valve[] valves = getPipeline().getValves();
for (Valve valve : valves) {if (errorValve.equals(valve.getClass().getName())) {
found = true;
break;
}
}
if(!found) {
Valve valve =
(Valve) Class.forName(errorValve).getConstructor().newInstance();
getPipeline().addValve(valve);
}
} catch (Throwable t) {ExceptionUtils.handleThrowable(t);
log.error(sm.getString(
"standardHost.invalidErrorReportValveClass",
errorValve), t);
}
}
super.startInternal();}
Host
的实例化,是通过设置生命周期状态来进行促发生命周期事件 fireLifecycleEvent
来执行后续工作的。
deployApps
:解决host
下多个利用deployDirectories
:解决host
上面以目录形式部署的(results.add(),这里也是以多线程的形式并行执行的)host.addChild()
:这时猜触发context
实例核心内容context
:具体读取web.xml
封装wrapper
过程应用事件驱动交给ContextConfig
(它也是一个事件监听器)
9. MapperListener.startInternal()
public void startInternal() throws LifecycleException {setState(LifecycleState.STARTING);
// 失去 engine 容器
Engine engine = service.getContainer();
if (engine == null) {return;}
// 找到默认主机
findDefaultHost();
// 为以后容器以及子容器增加监听器
addListeners(engine);
// 注册 engine 下所有的 host
Container[] conHosts = engine.findChildren();
for (Container conHost : conHosts) {Host host = (Host) conHost;
if (!LifecycleState.NEW.equals(host.getState())) {
// 注册上下文和包装器
registerHost(host);
}
}
}
10. Connector.startInternal()
截至到这里,容器的注册与启动曾经实现了,接下来到连接器的启动了
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 {protocolHandler.start();
} catch (Exception e) {
throw new LifecycleException(sm.getString("coyoteConnector.protocolHandlerStartFailed"), e);
}
}
11. AbstractProtocol.start()
这里对 EndPoint
进行初始化
public void start() throws Exception {if (getLog().isInfoEnabled()) {getLog().info(sm.getString("abstractProtocolHandler.start", getName()));
}
endpoint.start();
// Start timeout thread
asyncTimeout = new AsyncTimeout();
Thread timeoutThread = new Thread(asyncTimeout, getNameInternal() + "-AsyncTimeout");
int priority = endpoint.getThreadPriority();
if (priority < Thread.MIN_PRIORITY || priority > Thread.MAX_PRIORITY) {priority = Thread.NORM_PRIORITY;}
timeoutThread.setPriority(priority);
timeoutThread.setDaemon(true);
timeoutThread.start();}
12. AbstractEndpoint.start()
public final void start() throws Exception {if (bindState == BindState.UNBOUND) {bind();
bindState = BindState.BOUND_ON_START;
}
startInternal();}
13. NioEndpoint.bind()
public void bind() throws Exception {if (!getUseInheritedChannel()) {
// 获取 nio 通道 channel
serverSock = ServerSocketChannel.open();
socketProperties.setProperties(serverSock.socket());
InetSocketAddress addr = (getAddress()!=null?new InetSocketAddress(getAddress(),getPort()):new InetSocketAddress(getPort()));
// 绑定端口,但尚未应用 accept 获取客户端连贯
serverSock.socket().bind(addr,getAcceptCount());
} else {
// Retrieve the channel provided by the OS
Channel ic = System.inheritedChannel();
if (ic instanceof ServerSocketChannel) {serverSock = (ServerSocketChannel) ic;
}
if (serverSock == null) {throw new IllegalArgumentException(sm.getString("endpoint.init.bind.inherited"));
}
}
serverSock.configureBlocking(true); //mimic APR behavior
// Initialize thread count defaults for acceptor, poller
if (acceptorThreadCount == 0) {
// FIXME: Doesn't seem to work that well with multiple accept threads
acceptorThreadCount = 1;
}
if (pollerThreadCount <= 0) {
//minimum one poller thread
pollerThreadCount = 1;
}
setStopLatch(new CountDownLatch(pollerThreadCount));
// Initialize SSL if needed
initialiseSsl();
selectorPool.open();}
14. NioEndpoint.startInternal()
这里通过 startAcceptorThreads
启动 Accepter
线程,该线程用于接管新的 Socket
连贯
总结
正文完