你可能不那么知道的Tomcat生命周期管理 | 博学谷狂野架构师
Tomcat生命周期管理
各种组件如何统一管理
Tomcat的架构设计是清晰的、模块化、它拥有很多组件,加入在启动Tomcat时一个一个组件启动,很容易遗漏组件,同时还会对后面的动态组件拓展带来麻烦。如果采用我们传统的方式的话,组件在启动过程中如果发生异常,会很难管理,比如你的下一个组件调用了start方法,但是如果它的上级组件还没有start甚至还没有init的话,Tomcat的启动会非常难管理,因此,Tomcat的设计者提出一个解决方案:用Lifecycle管理启动,停止、关闭。
生命周期统一接口
Tomcat内部架构中各个核心组件有包含与被包含关系,例如:Server包含了Service.Service又包含了Container和Connector,这个结构有一点像数据结构中的树,树的根结点没有父节点,其他节点有且仅有一个父节点,每一个父节点有0至多个子节点。所以,我们可以通过父容器启动它的子容器,这样只要启动根容器,就可以把其他所有的容器都启动,从而达到了统一的启动,停止、关闭的效果。
所有所有组件有一个统一的接口——Lifecycle,把所有的启动、停止、关闭、生命周期相关的方法都组织到一起,就可以很方便管理Tomcat各个容器组件的生命周期。
Lifecycle其实就是定义了一些状态常量和几个方法,主要方法是init,start,stop三个方法。
例如:Tomcat的Server组件的init负责遍历调用其包含所有的Service组件的init方法。
注意:Server只是一个接口,实现类为StandardServer,有意思的是,StandardServer没有init方法,init方法是在哪里,其实是在它的父类LifecycleBase中,这个类就是统一的生命周期管理。
COPYpublic class StandardService extends LifecycleMBeanBase implements Service public abstract class LifecycleMBeanBase extends LifecycleBase implements JmxEnabled
LifecycleBase
COPYpublic abstract class LifecycleBase implements Lifecycle { @Override public final synchronized void init() throws LifecycleException { //这个就是为了防止 组件启动的顺序不对 if (!state.equals(LifecycleState.NEW)) { invalidTransition(Lifecycle.BEFORE_INIT_EVENT); } try { //只打印核心组件 if(this.getClass().getName().startsWith("org.apache.catalina.core")||this.getClass().getName().startsWith("org.apache.catalina.connector")){ System.out.println(this.getClass()+"--init()"); } setStateInternal(LifecycleState.INITIALIZING, null, false); //调用子类的initInternal方法 initInternal(); setStateInternal(LifecycleState.INITIALIZED, null, false); } catch (Throwable t) { handleSubClassException(t, "lifecycleBase.initFail", toString()); } } }
所以StandardServer最终只会调用到initInternal方法,这个方法会初始化子容器Service的init方法
为什么LifecycleBase这么玩,其实很多架构源码都是这么玩的,包括JDK的容器源码都是这么玩的,一个类,有一个接口,同时抽象一个抽象骨架类,把通用的实现放在抽象骨架类中,这样设计就方便组件的管理,使用LifecycleBase骨架抽象类,在抽象方法中就可以进行统一的处理。
LifeCycle源码分析
作用
组件生命周期方法的通用接口。 Catalina组件可以实现此接口(以及它们支持的功能的适当接口),以便提供一致的机制来启动和停止组件
状态图
Tomcat中的事件触发是通过这些状态来判定的。
COPY* start() * ----------------------------- * | | * | init() | * NEW -»-- INITIALIZING | * | | | | ------------------«----------------------- * | | |auto | | | * | | \|/ start() \|/ \|/ auto auto stop() | * | | INITIALIZED --»-- STARTING_PREP --»- STARTING --»- STARTED --»--- | * | | | | | * | |destroy()| | | * | --»-----«-- ------------------------«-------------------------------- ^ * | | | | * | | \|/ auto auto start() | * | | STOPPING_PREP ----»---- STOPPING ------»----- STOPPED -----»----- * | \|/ ^ | ^ * | | stop() | | | * | | -------------------------- | | * | | | | | * | | | destroy() destroy() | | * | | FAILED ----»------ DESTROYING ---«----------------- | * | | ^ | | * | | destroy() | |auto | * | --------»----------------- \|/ | * | DESTROYED | * | | * | stop() | * ----»-----------------------------»------------------------------
接口定义
Lifecycle接口统一管理Tomcat生命周期。一共做了4件事:
- 定义13个string类型常量,用于LifecycleEvent时间的type属性中,用于区分组件发出的LifecycleEvent事件时的状态。
- 定义三个管理监听器的方法,addLifecycleListener、findLifecycleListeners、removeLifecycleListener。
- 定义4个生命周期的方法,init、start、stop、destory,用于执行生命周期的各个阶段的操作。
- 定义了获取当前状态的两个方法,getState、getStateName、用于获取当前的状态。
COPYpublic interface Lifecycle { // 13个状态常量值 public static final String BEFORE_INIT_EVENT = "before_init"; public static final String AFTER_INIT_EVENT = "after_init"; public static final String START_EVENT = "start"; public static final String BEFORE_START_EVENT = "before_start"; public static final String AFTER_START_EVENT = "after_start"; public static final String STOP_EVENT = "stop"; public static final String BEFORE_STOP_EVENT = "before_stop"; public static final String AFTER_STOP_EVENT = "after_stop"; public static final String AFTER_DESTROY_EVENT = "after_destroy"; public static final String BEFORE_DESTROY_EVENT = "before_destroy"; public static final String PERIODIC_EVENT = "periodic"; public static final String CONFIGURE_START_EVENT = "configure_start"; public static final String CONFIGURE_STOP_EVENT = "configure_stop"; // 3个监听器方法 public void addLifecycleListener(LifecycleListener listener); public LifecycleListener[] findLifecycleListeners(); public void removeLifecycleListener(LifecycleListener listener); // 4个生命周期方法 public void init() throws LifecycleException; public void start() throws LifecycleException; public void stop() throws LifecycleException; public void destroy() throws LifecycleException; // 2个当前状态方法 public LifecycleState getState(); public String getStateName(); }
默认实现类
COPYpublic abstract class LifecycleBase implements Lifecycle { // 源组件的当前状态,不同状态触发不同事件 private volatile LifecycleState state = LifecycleState.NEW; }
监听器相关方法
事件监听器需要三个参与者:
- 事件对象:用于封装事件的信息,在事件监听器接口的同一方法中作为参数使用,继承自java.util.EventObject类。
- 事件源:触发事件的源头,不同事件源触发不同事件类型。
- 事件监听器:负责监听事件源发出的事件。实现 java.util.EventListener 接口。
COPY// 用于事件通知的已注册LifecycleListener列表 private final List<LifecycleListener> lifecycleListeners = new CopyOnWriteArrayList<>(); @Override public void addLifecycleListener(LifecycleListener listener) { lifecycleListeners.add(listener); } @Override public LifecycleListener[] findLifecycleListeners() { return lifecycleListeners.toArray(new LifecycleListener[0]); } @Override public void removeLifecycleListener(LifecycleListener listener) { lifecycleListeners.remove(listener); } // 子类根据当前状态触发不同事件,实现不同操作 protected void fireLifecycleEvent(String type, Object data) { LifecycleEvent event = new LifecycleEvent(this, type, data); for (LifecycleListener listener : lifecycleListeners) { listener.lifecycleEvent(event); } }
生命周期方法
LifecycleBase 类是Lifecycle 接口的默认实现,所有实现了生命周期的组件都直接或者间接的继承自LifecycleBase。
init方法
COPY@Override public final synchronized void init() throws LifecycleException { // 只有 NEW 状态可以调用 if (!state.equals(LifecycleState.NEW)) { invalidTransition(Lifecycle.BEFORE_INIT_EVENT); } // 设置 生命周期状态 -- INITIALIZING,触发相应事件 setStateInternal(LifecycleState.INITIALIZING, null, false); // 模板方法,由具体子类实现 initInternal(); // 执行完成,设置生命周期状态 -- INITIALIZED,触发相应事件 setStateInternal(LifecycleState.INITIALIZED, null, false); }
Start方法
COPY@Override public final synchronized void start() throws LifecycleException { // 此三种状态不执行 if (LifecycleState.STARTING_PREP.equals(state) || LifecycleState.STARTING.equals(state) || LifecycleState.STARTED.equals(state)) { return; } // NEW 状态 执行 init 方法 if (state.equals(LifecycleState.NEW)) { init(); // 启动失败,调用 stop 方法 } else if (state.equals(LifecycleState.FAILED)) { stop(); // 其它状态,非法操作 } else if (!state.equals(LifecycleState.INITIALIZED) && !state.equals(LifecycleState.STOPPED)) { throw new LifecycleException() } // 设置启动状态为 STARTING_PREP【开始准备】 setStateInternal(LifecycleState.STARTING_PREP, null, false); startInternal(); // 调用完成后判断组件启动状态 if (state.equals(LifecycleState.FAILED)) { stop(); } else if (!state.equals(LifecycleState.STARTING)) { throw new LifecycleException(); } else { setStateInternal(LifecycleState.STARTED, null, false); } }
stop方法
COPY@Override public final synchronized void stop() throws LifecycleException { // STOPPING_PREP、STOPPING、STOPPED此三种状态不予执行 if (LifecycleState.STOPPING_PREP.equals(state) || LifecycleState.STOPPING.equals(state) || LifecycleState.STOPPED.equals(state)) { return; } // 如果状态为 NEW、修改为 STOPPED if (state.equals(LifecycleState.NEW)) { state = LifecycleState.STOPPED; return; } // 不为 STARTED、FAILED 2种状态,抛出异常 if (!state.equals(LifecycleState.STARTED) && !state.equals(LifecycleState.FAILED)) { throw new LifecycleException(); } try { // 启动失败,触发事件,否则设置生命周期状态 if (state.equals(LifecycleState.FAILED)) { fireLifecycleEvent(BEFORE_STOP_EVENT, null); } else { setStateInternal(LifecycleState.STOPPING_PREP, null, false); } // 调用模板方法 stopInternal(); if (!state.equals(LifecycleState.STOPPING) && !state.equals(LifecycleState.FAILED)) { throw new LifecycleException(); } setStateInternal(LifecycleState.STOPPED, null, false); } catch (Throwable t) { setStateInternal(LifecycleState.FAILED, null, false); throw new LifecycleException(); } finally { if (this instanceof Lifecycle.SingleUse) { setStateInternal(LifecycleState.STOPPED, null, false); destroy(); } } }
destroy方法
COPY@Override public final synchronized void destroy() throws LifecycleException { // 启动失败,先调用 stop 方法 if (LifecycleState.FAILED.equals(state)) { stop(); } // DESTROYING、DESTROYED不执行了 if (LifecycleState.DESTROYING.equals(state) || LifecycleState.DESTROYED.equals(state)) { return; } // 非法状态 if (!state.equals(LifecycleState.STOPPED) && !state.equals(LifecycleState.FAILED) && !state.equals(LifecycleState.NEW) && !state.equals(LifecycleState.INITIALIZED)) { throw new LifecycleException(); } try { setStateInternal(LifecycleState.DESTROYING, null, false); destroyInternal(); setStateInternal(LifecycleState.DESTROYED, null, false); } catch (Throwable t) { setStateInternal(LifecycleState.FAILED, null, false); throw new LifecycleException(); } }
设置状态方法
COPYprivate synchronized void setStateInternal(LifecycleState state, Object data, boolean check) throws LifecycleException { // 检查参数 if (check) { if (state == null) { throw new LifecycleException(); return; } if (!(state == LifecycleState.FAILED || (this.state == LifecycleState.STARTING_PREP && state == LifecycleState.STARTING) || (this.state == LifecycleState.STOPPING_PREP && state == LifecycleState.STOPPING) || (this.state == LifecycleState.FAILED && state == LifecycleState.STOPPING))) { throw new LifecycleException(); } } this.state = state; String lifecycleEvent = state.getLifecycleEvent(); if (lifecycleEvent != null) { fireLifecycleEvent(lifecycleEvent, data); } }
监听机制
事件监听器需要三个参与者:
- 事件对象—用于封装事件的信息,在事件监听器接口的统一方法中作为参数,一般继承 java.util.EventObjecct类。
- 事件源—触发事件对的源头,不同事件源触发不同事件。
- 事件监听器—负责监听事件源发出的事件,发生事件时,事件源调用事件监听器的统一方法处理。监听器一般实现java.util.EventListener接口。
COPYpublic final class LifecycleEvent extends java.util.EventObject { public LifecycleEvent(Lifecycle lifecycle, String type, Object data) { super(lifecycle); this.type = type; this.data = data; } } COPYpublic interface LifecycleListener { public void lifecycleEvent(LifecycleEvent event); } COPYpublic class HostConfig implements LifecycleListener { @Override public void lifecycleEvent(LifecycleEvent event) { try { host = (Host) event.getLifecycle(); if (host instanceof StandardHost) { setCopyXML(((StandardHost) host).isCopyXML()); setDeployXML(((StandardHost) host).isDeployXML()); setUnpackWARs(((StandardHost) host).isUnpackWARs()); setContextClass(((StandardHost) host).getContextClass()); } } catch (ClassCastException e) { return; } // Process the event that has occurred if (event.getType().equals(Lifecycle.PERIODIC_EVENT)) { check(); } else if (event.getType().equals(Lifecycle.BEFORE_START_EVENT)) { beforeStart(); } else if (event.getType().equals(Lifecycle.START_EVENT)) { start(); } else if (event.getType().equals(Lifecycle.STOP_EVENT)) { stop(); } } } COPY// LifecycleBase.startInternal this.state = state; String lifecycleEvent = state.getLifecycleEvent(); if (lifecycleEvent != null) { fireLifecycleEvent(lifecycleEvent, data); } protected void fireLifecycleEvent(String type, Object data) { LifecycleEvent event = new LifecycleEvent(this, type, data); for (LifecycleListener listener : lifecycleListeners) { listener.lifecycleEvent(event); } }
模板方法
四个模板方法,由子类具体实现
COPYprotected abstract void initInternal() throws LifecycleException; protected abstract void startInternal() throws LifecycleException; protected abstract void stopInternal() throws LifecycleException; protected abstract void destroyInternal() throws LifecycleException;
总结
通过提供init、start、stop、destory方法,通过相应的模板方法【模板设计模式】,提供组件的统一生命周期的管理、事件调度。
本文由
传智教育博学谷狂野架构师
教研团队发布。如果本文对您有帮助,欢迎
关注
和点赞
;如果您有任何建议也可留言评论
或私信
,您的支持是我坚持创作的动力。转载请注明出处!

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
大数据计算引擎 EasyMR:拥抱开源,引领技术创新
身处数字经济时代,随着大数据应用越来越广泛,越来越多的企业和组织开始关注大数据基础平台的建设和运营。在认识到其的重要性之后,如何具体着手搭建或采购大数据基础平台成为下一步需要解决的问题。 在大数据基础平台中,大数据组件是非常重要的一部分,包括数据存储、数据处理、数据分析、数据可视化等。在选择大数据组件时,我们常常在闭源组件和开源组件选择中反复纠结。 本文将从优势、劣势两个维度分析开源组件、闭源组件对大数据基础平台建设的影响,并结合袋鼠云自研的大数据计算引擎 EasyMR 的实践经历进行分享。 开源组件 在大数据领域,开源组件已经成为了构建大数据平台的重要基石。例如 Hadoop、Spark、Hive、HBase、Kafka、Storm、Flink 等开源软件已经成为了大数据处理和分析的主要工具。 这些开源组件不仅提供了高效、可扩展、可靠的大数据处理和存储能力,而且还促进了生态系统的发展,形成了庞大的开发社区和丰富的第三方工具及应用程序。 优势 ● 免费 开源组件一般都是免费的,其源代码是公开的,任何人都可以下载、使用、修改和分发,这将极大降低企业的开发和建设成本。 ● 灵活性 由于源代...
- 下一篇
扫一扫,原来这么简单
二维码识别技术已广泛应用在移动支付、实用工具、电商购物、社交通讯等场景。然而,在实际生活中,二维码容易遇到距离远、暗光、强光、污损、模糊和大角度倾斜等复杂场景,导致识别困难,扫码体验差。华为HMS Core 统一扫码服务(Scan Kit)为开发者们的APP带来一站式扫码解决方案,并且拥有高识别率和快速识别等特点。 距离太远、码图过小? 在停车场扫码缴费、上课扫码签到、广告牌宣传等实际生活场景中,二维码的尺寸不一,一般的扫码功能需手动调节手机相机框与二维码的距离直到合适的扫码大小,实属不便。统一扫码服务基于自研的深度学习算法模型,遇到远距离场景、码图过小、甚至肉眼无法分辨的情况,支持自动检测放大,智能识别。 多角度、光线不佳、模糊等复杂场景无法识别? 餐桌、共享单车、充电桩等设备上的二维码,易受环境或人为影响,导致污损、模糊、反光,无法清晰展示,造成识别困难。统一扫码服务基于多项计算机视觉技术,可以大幅提升复杂场景识别率,统一扫码服务可以自动检测及旋转纠正,能够在识别任意角度的同时保证准确率。 单个扫码效率低? 在录入商品信息、快递信息等需要频繁扫码的场景中,一般的扫码功能识别成功后会...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS8安装Docker,最新的服务器搭配容器使用
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- Windows10,CentOS7,CentOS8安装Nodejs环境
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS8编译安装MySQL8.0.19