tomcat源码解析(四)——tomcat基本结构简述
来源:互联网 发布:ps是什么网络用语 编辑:程序博客网 时间:2024/05/16 17:31
关于tomcat结构,其生命周期管理方式为自上而下;在tomcat6中,每一个关键组件都实现了Lifecycle接口;而在tomcat9中,每个组件都继承了LifecycleMBeanBase类,而LifecycleMBeanBase类继承了LifecycleBase类,在LifecycleBase中实现了Lifecycle接口;所以Lifecycle是管理各个重要组件生命周期的关键;
本文将以tomcat-9.0.0.M9的源码为基础;在对具体生命周期说明之前,需要了解其基本组件的结构;
这里图中只包括了最主要的几个部分,这几个类也是tomcat中最基本的实现;
StandardServer:是tomcat状态管理的主要类,通过它管理下面多个service服务,即一个tomcat管理多个web工程;
StandardService:每个web工程对应一个StandardService;
StandardThreadExecutor:线程池;
Connector:网络接口模块;
StandardEngine:执行类;
StandardHost:一般负责管理域名部分;
StandardContext:负责管理context部分;
StandardWrapper:映射具体的URL资源;
对以上各个模块认知深度还不够,但具体的理解可以分而治之,逐个部分去进行了解。
以上各组件实际上是与server.xml相互对应的,一般通过简单的配置xml就可以修改各组件的配置。
通过我对tomcat9的server.xml解析部分的源码解读;反推出了一个较为完整的文件的节点配置结构:
这上面只有节点的名称,对应的xml中配置的节点;图中的父节点指向子节点;每个节点的属性则需要在对各功能模块深入了解中,才能明白作用。
图中的server、service、engine、host、context、executor等,与基本组件相互对应。
从上图中,可以对tomcat的所有功能模块有大概的认知。从中可以发现一些较为核心的节点;例如GlobalNamingResources、Connector、Cluster、Context等,这些模块涉及功能较多,也是具体实现的关键。
接口Lifecycle中包含了对组件行为的约束,init、start、stop、destory等,以及内部的监听。
在tomcat9中,抽象程度比tomcat6更高,在版本6中各组件直接实现接口;在版本9中则由LifecycleBase抽象类实现,其中实现了对事件的监听,而将具体的事件业务逻辑交给子类实现,这样使得各组件更专注于业务功能。
以init的源码为例(其他的基本相同):
@Override public final synchronized void init() throws LifecycleException { if (!state.equals(LifecycleState.NEW)) { invalidTransition(Lifecycle.BEFORE_INIT_EVENT); } setStateInternal(LifecycleState.INITIALIZING, null, false); try { initInternal(); } catch (Throwable t) { ExceptionUtils.handleThrowable(t); setStateInternal(LifecycleState.FAILED, null, false); throw new LifecycleException( sm.getString("lifecycleBase.initFail",toString()), t); } setStateInternal(LifecycleState.INITIALIZED, null, false); } protected abstract void initInternal() throws LifecycleException;子类只需要覆盖initInternal()方法,而且只关心自己所需要的初始化逻辑,事件监听逻辑在这里已经完成。
LifecycleMBeanBase类继承了LifecycleBase,里面实现了JmxEnabled接口;加入了对MBean的支持,自动注册各组件,实现JMX管理,以及对注册的事件管理;
ContainerBase类继承了LifecycleMBeanBase,添加了对容器具体功能的实现,其子类例如StandardEngine、StandardHost、StandardContext、StandardWrapper等。
tomcat9中重要的组件都会继承LifecycleMBeanBase类,例如StandardServer、StandardService、StandardEngine等。
在Catalina类的load方法中首先在解析server.xml时通过Digester类,将各组件初始化完成;
接下来在执行
getServer().init();
getServer().start();
等方法,实际对应的是StandardServer类的对象;通过操作StandardServer的对象,来完成对所有组件生命周期的管理;
以start为例,在LifecycleBase中已经实现start方法,组件只需实现startInternal()方法;
StandardServer源码如下:
/** * Start nested components ({@link Service}s) and implement the requirements * of {@link org.apache.catalina.util.LifecycleBase#startInternal()}. * * @exception LifecycleException if this component detects a fatal error * that prevents this component from being used */ @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(); } } }这里实现自己全局属性初始化后调用了services[i].start();,以此实现自己管理的service;
这里对应的service是StandardService;同理可以查看StandardService类的startInternal()方法;
/** * Start nested components ({@link Executor}s, {@link Connector}s and * {@link Container}s) and implement the requirements of * {@link org.apache.catalina.util.LifecycleBase#startInternal()}. * * @exception LifecycleException if this component detects a fatal error * that prevents this component from being used */ @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 (engine != null) { synchronized (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); } } } }这里也是先实现自己管理各组件的启动,如最之前图中的描述的组件engine、executor、connector;
其中只拿engine为例,对应的是StandardEngine,继承自ContainerBase;
StandardEngine的startInternal()方法调用super.startInternal();即是调用ContainerBase的startInternal()方法;
ContainerBase的startInternal()源码如下:
/** * Start this component and implement the requirements * of {@link org.apache.catalina.util.LifecycleBase#startInternal()}. * * @exception LifecycleException if this component detects a fatal error * that prevents this component from being used */ @Override protected synchronized void startInternal() throws LifecycleException { // Start our subordinate components, if any logger = null; getLogger(); Cluster cluster = getClusterInternal(); if (cluster instanceof Lifecycle) { ((Lifecycle) cluster).start(); } Realm realm = getRealmInternal(); if (realm instanceof Lifecycle) { ((Lifecycle) realm).start(); } // Start our child containers, if any 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]))); } boolean fail = false; for (Future<Void> 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")); } // 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(); }这段代码也是对各个组件执行启动操作;
在这段代码中StandardEngine启动StandardHost则分为两步,先将StandardHost的对象加入列表,之后通过线程池启动;对应的代码如下:
</pre></p><p><pre name="code" class="java">
// Start our child containers, if any 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]))); } boolean fail = false; for (Future<Void> result : results) { try { result.get(); } catch (Exception e) { log.error(sm.getString("containerBase.threadedStartFailed"), e); fail = true; } }在此之后的启动代码都是类似的,StandardHost管理StandardContext,StandardContext管理StandardWrapper;而每个组件除此之外还有管理自己的特有的模块组件;
剩下的可以依次类推,至此组件管理方面结束;接下来的源码解析就是对内部各个模块功能跟踪。
- tomcat源码解析(四)——tomcat基本结构简述
- Tomcat源码解析(四):session管理
- Tomcat关闭过程(Tomcat源码解析四)
- Tomcat关闭过程(Tomcat源码解析四)
- tomcat源码浅析(四)之web.xml解析
- Tomcat源码解析(四):tomcat核心组件初始化和启动
- (十)Tomcat源码解析 - Tomcat总结
- Tomcat源码解读系列(四)——Tomcat类加载机制概述
- Tomcat源码解读系列(四)——Tomcat类加载机制概述
- Tomcat源码解读系列(四)——Tomcat类加载机制概述
- tomcat源码解析(一)
- Tomcat 源码解析(1)
- Tomcat源码解析(1)
- Tomcat源码解析(2)
- Tomcat源码解析(3)
- Tomcat源码解析(4)
- Tomcat源码解析(5)
- Tomcat源码解析(6)
- 页面回车操作
- ios网络框架
- 修改C:\WINDOWS\system32\drivers\etc\hosts 文件有什么作用
- http://www.cnblogs.com/90zeng/
- POJ 1258 (简单最小生成树,prim算法)
- tomcat源码解析(四)——tomcat基本结构简述
- 反转链表
- eclipse下使用动态库、静态库相应的配置
- hdu5791
- JVM总结
- LabVIEW时间格式字符串输出
- 策略模式
- Quartz Cron表达式 在线生成器
- [Cloud Computing]Patterns: Elastic Network Capacity