Tomcat的核心作用是Servlet容器,
Tomcat中Engine,Host,Context,Wrapper有一个骨架类org.apache.catalina.core.ContainerBase,
ContainerBase
protected final HashMap<String, Container> children = new HashMap<>();
protected Container parent = null;
protected Pipeline pipeline = new StandardPipeline(this);
protected ArrayList<ContainerListener> listeners = new ArrayList<ContainerListener>();
protected synchronized void startInternal() throws LifecycleException {
...
//后台共享线程在容器启动后调用.
threadStart();
}
protected void threadStart() {
...
threadDone = false;
String threadName = "ContainerBackgroundProcessor[" + toString() + "]";
thread = new Thread(new ContainerBackgroundProcessor(), threadName);
thread.setDaemon(true);
thread.start();
}
public void backgroundProcess() {
cluster.backgroundProcess();
loader.backgroundProcess();
manager.backgroundProcess();
Realm realm = getRealmInternal();
realm.backgroundProcess();
Valve current = pipeline.getFirst();
while (current != null) {
current.backgroundProcess();
current = current.getNext();
}
fireLifecycleEvent(Lifecycle.PERIODIC_EVENT, null);
}
从上面源码我们可以看到, 容器包含父子关系(有children容器),
每个容器内部都有一个pipeline,请求在各容器内部管道中的阀门间传递.
ContainerBase.backgroundProcess()中可以看到如下任务:
(1)Cluster的后台任务:发送心跳包,监听集群部署的改变(Engine和Host包含)
(2)Realm的后台任务,如果子类定义实现了话(Engine,Host,Context包含);
(3)整个Valve链中每个Valve的后台任务,
(4)Loader的后台任务,Context的reload设置为true,将会在后台任务中周期性检查资源(包括WEB-INF/classes下的类文件和WEB-INF/lib中的jar包)是否修改,如果发现修改将调用StandardContext.reload()进行重启
(5)Manager的后台任务,ManagerBase实现了会话管理的一个重要任务:将所有超时的会话进行失效,并进行清理(从Manager的session集合中删除);
(6)WebResourceRoot的后台任务,上面Loader也是基于WebResourceRoot的,但WebResourceRoot除了class文件和jar包之外,还包括Web应用中其他所有资源的抽象,它的后台任务主要是清除过时的缓存记录。
(7)启动子容器任务线程池. 子容器的启动是通过线程池来实现的.
//org.apache.catalina.core.ContainerBase#startInternal
Container children[] = findChildren();
List<Future<Void>> results = new ArrayList<Future<Void>>();
for (int i = 0; i < children.length; i++) {
results.add(startStopExecutor.submit(new StartChild(children[i])));
}
boolean fail = false;
for (Future<Void> result : results) {
result.get();
}
Tomcat中的运行时监控/管理和JMX
如果查看你就会发现组件并不是直接派生子LifecycleBase的,而是派生自LifecycleMBeanBase
public abstract class ContainerBase extends LifecycleMBeanBase{}
public abstract class LifecycleMBeanBase extends LifecycleBase
implements MBeanRegistration
{}
这个类除了继承了Lifecyle这条设计路线外还引入了JMX的功能。简单来说,就是Tomcat为了使用JMX提供的监控和管理能力,其组件可以作为MBean可以注册到MBeanServer中,从而我们可以在运行时对Tomcat进行管理和监控。
注入过程:
@Override
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());
}
}