前言
通过上面一篇的介绍,Service主要启动了Container和Connector,我们先来看Container容器。
Container的子类关系图
Container关系图.png由上图知道,Container有四个子容器,分别为:
Engine:引擎,用来管理多个站点,一个Service最多只能有一个;
Host:代表一个站点,或者叫做虚拟主机,一个Engine可以包含多个Host;
Context:代表一个应用,一个Host可以包含多个Context;
Wrapper:每个Wrapper封装着一个Servlet,一个Context可以包含多个Wrapper。
下面我们一个一个来介绍。
ContainerBase
同样ContainerBase也遵循Lifecycle机制。
- initInternal()方法
protected void initInternal() throws LifecycleException {
reconfigureStartStopExecutor(getStartStopThreads());
super.initInternal();
}
private void reconfigureStartStopExecutor(int threads) {
// threads一般默认为1,startStopExecutor用来处理其子容器的启动和停止事件
if (threads == 1) {
// Use a fake executor
if (!(startStopExecutor instanceof InlineExecutorService)) {
startStopExecutor = new InlineExecutorService();
}
} else {
// Delegate utility execution to the Service
Server server = Container.getService(this).getServer();
server.setUtilityThreads(threads);
startStopExecutor = server.getUtilityExecutor();
}
}
这里主要初始化startStopExecutor线程池,用来处理其子容器的启动和停止事件的线程池。
- startInternal()方法
protected synchronized void startInternal() throws LifecycleException {
// Start our subordinate components, if any
logger = null;
getLogger();
//1. 集群和认证相关
Cluster cluster = getClusterInternal();
if (cluster instanceof Lifecycle) {
((Lifecycle) cluster).start();
}
Realm realm = getRealmInternal();
if (realm instanceof Lifecycle) {
((Lifecycle) realm).start();
}
//2. 启动子容器
Container children[] = findChildren();
List<Future<Void>> results = new ArrayList<>();
for (int i = 0; i < children.length; i++) {
results.add(startStopExecutor.submit(new StartChild(children[i])));
}
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());
}
//3. 启动管道
if (pipeline instanceof Lifecycle) {
((Lifecycle) pipeline).start();
}
//4. 设置状态,发送通知
setState(LifecycleState.STARTING);
//5. 如果backgroundProcessorDelay>0,启动定时器进行延时处理
if (backgroundProcessorDelay > 0) {
monitorFuture = Container.getService(ContainerBase.this).getServer()
.getUtilityExecutor().scheduleWithFixedDelay(
new ContainerBackgroundProcessorMonitor(), 0, 60, TimeUnit.SECONDS);
}
}
这里主要通过startStopExecutor线程池来执行子容器的启动,并且启动子容器对应的管道(每个子容器都有自己对应的管道,后面会介绍)。
ValveBase&&StandardPipeline
ValveBase作为所有子容器阀的抽想实现类,其初始化执行了其父类LifecycleMBeanBase的初始化方法,启动仅仅设置了容器的状态,所以这里不介绍了。
protected void initInternal() throws LifecycleException {
super.initInternal();
containerLog = getContainer().getLogger();
}
protected synchronized void startInternal() throws LifecycleException {
setState(LifecycleState.STARTING);
}
StandardPipeline作为最基础的管道,仅仅实现了启动方法。
protected synchronized void startInternal() throws LifecycleException {
// Start the Valves in our pipeline (including the basic), if any
Valve current = first;
if (current == null) {
current = basic;
}
while (current != null) {
if (current instanceof Lifecycle)
((Lifecycle) current).start();
current = current.getNext();
}
setState(LifecycleState.STARTING);
}
该方法主要循环执行了每一个管道的start方法并设置其生命状态。
具体管道的介绍放在下一篇,这里不做过多描述。
StandardEngine
作为Engine的默认实现类,我们来看下他的启动。
- initInternal()方法
protected void initInternal() throws LifecycleException {
// Ensure that a Realm is present before any attempt is made to start
// one. This will create the default NullRealm if necessary.
getRealm();
super.initInternal();
}
这里调用其父类的初始化方法,上面已经介绍过了。
- startInternal()方法
protected synchronized void startInternal() throws LifecycleException {
// Log our server identification information
if (log.isInfoEnabled()) {
log.info(sm.getString("standardEngine.start", ServerInfo.getServerInfo()));
}
// Standard container startup
super.startInternal();
}
同样也是调用其父类的启动方法。
StandardEngineValve
默认使用其父类ValveBase的初始化和启动,不介绍。
StandardHost
Host的默认实现类,初始化和启动都是调用其父类的方法。
StandardHostValve
Host的默认管道类,初始化和启动都是调用其父类的方法。
StandardWrapper
Wrapper的默认实现类,初始化和启动都是调用其父类的方法。
StandardWrapperValve
Wrapper的默认管道类,初始化和启动都是调用其父类的方法。
总结
这里涉及到重要的管道内容,后面会有一篇专门介绍管道。
网友评论