你可能不那么知道的Tomcat生命周期管理 | 博学谷狂野架构师 ...

打印 上一主题 下一主题

主题 1013|帖子 1013|积分 3039

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中,这个类就是统一的生命周期管理。
  1. COPYpublic class StandardService extends LifecycleMBeanBase implements Service
  2.    
  3. public abstract class LifecycleMBeanBase extends LifecycleBase
  4.         implements JmxEnabled
复制代码
LifecycleBase
  1. COPYpublic abstract class LifecycleBase implements Lifecycle {
  2.       @Override
  3.     public final synchronized void init() throws LifecycleException {
  4.         //这个就是为了防止 组件启动的顺序不对
  5.         if (!state.equals(LifecycleState.NEW)) {
  6.             invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
  7.         }
  8.         try {
  9.             //只打印核心组件
  10.             if(this.getClass().getName().startsWith("org.apache.catalina.core")||this.getClass().getName().startsWith("org.apache.catalina.connector")){
  11.                 System.out.println(this.getClass()+"--init()");
  12.             }
  13.             setStateInternal(LifecycleState.INITIALIZING, null, false);
  14.             //调用子类的initInternal方法
  15.             initInternal();
  16.             setStateInternal(LifecycleState.INITIALIZED, null, false);
  17.         } catch (Throwable t) {
  18.             handleSubClassException(t, "lifecycleBase.initFail", toString());
  19.         }
  20.     }
  21.    
  22. }
复制代码
所以StandardServer最终只会调用到initInternal方法,这个方法会初始化子容器Service的init方法
为什么LifecycleBase这么玩,其实很多架构源码都是这么玩的,包括JDK的容器源码都是这么玩的,一个类,有一个接口,同时抽象一个抽象骨架类,把通用的实现放在抽象骨架类中,这样设计就方便组件的管理,使用LifecycleBase骨架抽象类,在抽象方法中就可以进行统一的处理。
LifeCycle源码分析

作用

组件生命周期方法的通用接口。 Catalina组件可以实现此接口(以及它们支持的功能的适当接口),以便提供一致的机制来启动和停止组件
状态图

Tomcat中的事件触发是通过这些状态来判定的。
  1. COPY*            start()
  2. *  -----------------------------
  3. *  |                           |
  4. *  | init()                    |
  5. * NEW -»-- INITIALIZING        |
  6. * | |           |              |     ------------------«-----------------------
  7. * | |           |auto          |     |                                        |
  8. * | |          \|/    start() \|/   \|/     auto          auto         stop() |
  9. * | |      INITIALIZED --»-- STARTING_PREP --»- STARTING --»- STARTED --»---  |
  10. * | |         |                                                            |  |
  11. * | |destroy()|                                                            |  |
  12. * | --»-----«--    ------------------------«--------------------------------  ^
  13. * |     |          |                                                          |
  14. * |     |         \|/          auto                 auto              start() |
  15. * |     |     STOPPING_PREP ----»---- STOPPING ------»----- STOPPED -----»-----
  16. * |    \|/                               ^                     |  ^
  17. * |     |               stop()           |                     |  |
  18. * |     |       --------------------------                     |  |
  19. * |     |       |                                              |  |
  20. * |     |       |    destroy()                       destroy() |  |
  21. * |     |    FAILED ----»------ DESTROYING ---«-----------------  |
  22. * |     |                        ^     |                          |
  23. * |     |     destroy()          |     |auto                      |
  24. * |     --------»-----------------    \|/                         |
  25. * |                                 DESTROYED                     |
  26. * |                                                               |
  27. * |                            stop()                             |
  28. * ----»-----------------------------»------------------------------
复制代码
接口定义

Lifecycle接口统一管理Tomcat生命周期。一共做了4件事:

  • 定义13个string类型常量,用于LifecycleEvent时间的type属性中,用于区分组件发出的LifecycleEvent事件时的状态。
  • 定义三个管理监听器的方法,addLifecycleListener、findLifecycleListeners、removeLifecycleListener。
  • 定义4个生命周期的方法,init、start、stop、destory,用于执行生命周期的各个阶段的操作。
  • 定义了获取当前状态的两个方法,getState、getStateName、用于获取当前的状态。
  1. COPYpublic interface Lifecycle {
  2.     // 13个状态常量值
  3.     public static final String BEFORE_INIT_EVENT = "before_init";
  4.     public static final String AFTER_INIT_EVENT = "after_init";
  5.     public static final String START_EVENT = "start";
  6.     public static final String BEFORE_START_EVENT = "before_start";
  7.     public static final String AFTER_START_EVENT = "after_start";
  8.     public static final String STOP_EVENT = "stop";
  9.     public static final String BEFORE_STOP_EVENT = "before_stop";
  10.     public static final String AFTER_STOP_EVENT = "after_stop";
  11.     public static final String AFTER_DESTROY_EVENT = "after_destroy";
  12.     public static final String BEFORE_DESTROY_EVENT = "before_destroy";
  13.     public static final String PERIODIC_EVENT = "periodic";
  14.     public static final String CONFIGURE_START_EVENT = "configure_start";
  15.     public static final String CONFIGURE_STOP_EVENT = "configure_stop";
  16.     // 3个监听器方法
  17.     public void addLifecycleListener(LifecycleListener listener);
  18.     public LifecycleListener[] findLifecycleListeners();
  19.     public void removeLifecycleListener(LifecycleListener listener);
  20.     // 4个生命周期方法
  21.     public void init() throws LifecycleException;
  22.     public void start() throws LifecycleException;
  23.     public void stop() throws LifecycleException;
  24.     public void destroy() throws LifecycleException;
  25.     // 2个当前状态方法
  26.     public LifecycleState getState();
  27.     public String getStateName();
  28. }
复制代码
默认实现类
  1. COPYpublic abstract class LifecycleBase implements Lifecycle {
  2.     // 源组件的当前状态,不同状态触发不同事件
  3.     private volatile LifecycleState state = LifecycleState.NEW;
  4. }
复制代码
监听器相关方法

事件监听器需要三个参与者:

  • 事件对象:用于封装事件的信息,在事件监听器接口的同一方法中作为参数使用,继承自java.util.EventObject类。
  • 事件源:触发事件的源头,不同事件源触发不同事件类型。
  • 事件监听器:负责监听事件源发出的事件。实现 java.util.EventListener 接口。
  1. COPY// 用于事件通知的已注册LifecycleListener列表
  2. private final List<LifecycleListener> lifecycleListeners =
  3.     new CopyOnWriteArrayList<>();
  4. @Override
  5. public void addLifecycleListener(LifecycleListener listener) {
  6.     lifecycleListeners.add(listener);
  7. }
  8. @Override
  9. public LifecycleListener[] findLifecycleListeners() {
  10.     return lifecycleListeners.toArray(new LifecycleListener[0]);
  11. }
  12. @Override
  13. public void removeLifecycleListener(LifecycleListener listener) {
  14.     lifecycleListeners.remove(listener);
  15. }
  16. // 子类根据当前状态触发不同事件,实现不同操作
  17. protected void fireLifecycleEvent(String type, Object data) {
  18.     LifecycleEvent event = new LifecycleEvent(this, type, data);
  19.     for (LifecycleListener listener : lifecycleListeners) {
  20.         listener.lifecycleEvent(event);
  21.     }
  22. }
复制代码
生命周期方法

LifecycleBase 类是Lifecycle 接口的默认实现,所有实现了生命周期的组件都直接或者间接的继承自LifecycleBase。
init方法
  1. COPY@Override
  2. public final synchronized void init() throws LifecycleException {
  3.     // 只有 NEW 状态可以调用
  4.     if (!state.equals(LifecycleState.NEW)) {
  5.         invalidTransition(Lifecycle.BEFORE_INIT_EVENT);
  6.     }
  7.     // 设置 生命周期状态 -- INITIALIZING,触发相应事件
  8.     setStateInternal(LifecycleState.INITIALIZING, null, false);
  9.     // 模板方法,由具体子类实现
  10.     initInternal();
  11.     // 执行完成,设置生命周期状态 -- INITIALIZED,触发相应事件
  12.     setStateInternal(LifecycleState.INITIALIZED, null, false);
  13. }
复制代码
Start方法
  1. COPY@Override
  2. public final synchronized void start() throws LifecycleException {
  3.     // 此三种状态不执行
  4.     if (LifecycleState.STARTING_PREP.equals(state) ||      
  5.         LifecycleState.STARTING.equals(state) ||
  6.         LifecycleState.STARTED.equals(state)) {
  7.         return;
  8.     }
  9.     // NEW 状态 执行 init 方法
  10.     if (state.equals(LifecycleState.NEW)) {
  11.         init();
  12.     // 启动失败,调用 stop 方法
  13.     } else if (state.equals(LifecycleState.FAILED)) {
  14.         stop();
  15.     // 其它状态,非法操作
  16.     } else if (!state.equals(LifecycleState.INITIALIZED) &&
  17.             !state.equals(LifecycleState.STOPPED)) {
  18.         throw new LifecycleException()
  19.     }
  20.     // 设置启动状态为 STARTING_PREP【开始准备】
  21.     setStateInternal(LifecycleState.STARTING_PREP, null, false);
  22.     startInternal();
  23.     // 调用完成后判断组件启动状态
  24.     if (state.equals(LifecycleState.FAILED)) {
  25.         stop();
  26.     } else if (!state.equals(LifecycleState.STARTING)) {
  27.         throw new LifecycleException();
  28.     } else {
  29.         setStateInternal(LifecycleState.STARTED, null, false);
  30.     }
  31. }
复制代码
stop方法
  1. COPY@Override
  2. public final synchronized void stop() throws LifecycleException {
  3.     // STOPPING_PREP、STOPPING、STOPPED此三种状态不予执行
  4.     if (LifecycleState.STOPPING_PREP.equals(state) ||
  5.         LifecycleState.STOPPING.equals(state) ||
  6.         LifecycleState.STOPPED.equals(state)) {
  7.         return;
  8.     }
  9.     // 如果状态为 NEW、修改为 STOPPED
  10.     if (state.equals(LifecycleState.NEW)) {
  11.         state = LifecycleState.STOPPED;
  12.         return;
  13.     }
  14.     // 不为 STARTED、FAILED 2种状态,抛出异常
  15.     if (!state.equals(LifecycleState.STARTED) &&
  16.         !state.equals(LifecycleState.FAILED)) {
  17.         throw new LifecycleException();
  18.     }
  19.     try {
  20.         // 启动失败,触发事件,否则设置生命周期状态
  21.         if (state.equals(LifecycleState.FAILED)) {
  22.             fireLifecycleEvent(BEFORE_STOP_EVENT, null);
  23.         } else {
  24.             setStateInternal(LifecycleState.STOPPING_PREP, null, false);
  25.         }
  26.         // 调用模板方法
  27.         stopInternal();
  28.         if (!state.equals(LifecycleState.STOPPING) &&
  29.             !state.equals(LifecycleState.FAILED)) {
  30.             throw new LifecycleException();
  31.         }
  32.         setStateInternal(LifecycleState.STOPPED, null, false);
  33.     } catch (Throwable t) {
  34.         setStateInternal(LifecycleState.FAILED, null, false);
  35.         throw new LifecycleException();
  36.     } finally {
  37.         if (this instanceof Lifecycle.SingleUse) {
  38.             setStateInternal(LifecycleState.STOPPED, null, false);
  39.             destroy();
  40.         }
  41.     }
  42. }
复制代码
destroy方法
  1. COPY@Override
  2. public final synchronized void destroy() throws LifecycleException {
  3.     // 启动失败,先调用 stop 方法
  4.     if (LifecycleState.FAILED.equals(state)) {
  5.         stop();
  6.     }
  7.     // DESTROYING、DESTROYED不执行了
  8.     if (LifecycleState.DESTROYING.equals(state) ||
  9.         LifecycleState.DESTROYED.equals(state)) {
  10.         return;
  11.     }
  12.     // 非法状态
  13.     if (!state.equals(LifecycleState.STOPPED) &&
  14.         !state.equals(LifecycleState.FAILED) &&
  15.         !state.equals(LifecycleState.NEW) &&
  16.         !state.equals(LifecycleState.INITIALIZED)) {
  17.         throw new LifecycleException();
  18.     }
  19.     try {
  20.         setStateInternal(LifecycleState.DESTROYING, null, false);
  21.         destroyInternal();
  22.         setStateInternal(LifecycleState.DESTROYED, null, false);
  23.     } catch (Throwable t) {
  24.         setStateInternal(LifecycleState.FAILED, null, false);
  25.         throw new LifecycleException();
  26.     }
  27. }
复制代码
设置状态方法
  1. COPYprivate synchronized void setStateInternal(LifecycleState state,
  2.         Object data, boolean check) throws LifecycleException {
  3.     // 检查参数
  4.     if (check) {
  5.         if (state == null) {
  6.             throw new LifecycleException();
  7.             return;
  8.         }
  9.         if (!(state == LifecycleState.FAILED ||
  10.                 (this.state == LifecycleState.STARTING_PREP &&
  11.                         state == LifecycleState.STARTING) ||
  12.                 (this.state == LifecycleState.STOPPING_PREP &&
  13.                         state == LifecycleState.STOPPING) ||
  14.                 (this.state == LifecycleState.FAILED &&
  15.                         state == LifecycleState.STOPPING))) {
  16.             throw new LifecycleException();
  17.         }
  18.     }
  19.     this.state = state;
  20.     String lifecycleEvent = state.getLifecycleEvent();
  21.     if (lifecycleEvent != null) {
  22.         fireLifecycleEvent(lifecycleEvent, data);
  23.     }
  24. }
复制代码
监听机制

事件监听器需要三个参与者:

  • 事件对象—用于封装事件的信息,在事件监听器接口的统一方法中作为参数,一般继承 java.util.EventObjecct类。
  • 事件源—触发事件对的源头,不同事件源触发不同事件。
  • 事件监听器—负责监听事件源发出的事件,发生事件时,事件源调用事件监听器的统一方法处理。监听器一般实现java.util.EventListener接口。
  1. COPYpublic final class LifecycleEvent extends java.util.EventObject {
  2.     public LifecycleEvent(Lifecycle lifecycle, String type, Object data) {
  3.         super(lifecycle);
  4.         this.type = type;
  5.         this.data = data;
  6.     }
  7. }
  8. COPYpublic interface LifecycleListener {
  9.     public void lifecycleEvent(LifecycleEvent event);
  10. }
  11. COPYpublic class HostConfig implements LifecycleListener {
  12.     @Override
  13.     public void lifecycleEvent(LifecycleEvent event) {
  14.         try {
  15.             host = (Host) event.getLifecycle();
  16.             if (host instanceof StandardHost) {
  17.                 setCopyXML(((StandardHost) host).isCopyXML());
  18.                 setDeployXML(((StandardHost) host).isDeployXML());
  19.                 setUnpackWARs(((StandardHost) host).isUnpackWARs());
  20.                 setContextClass(((StandardHost) host).getContextClass());
  21.             }
  22.         } catch (ClassCastException e) {
  23.             return;
  24.         }
  25.         // Process the event that has occurred
  26.         if (event.getType().equals(Lifecycle.PERIODIC_EVENT)) {
  27.             check();
  28.         } else if (event.getType().equals(Lifecycle.BEFORE_START_EVENT)) {
  29.             beforeStart();
  30.         } else if (event.getType().equals(Lifecycle.START_EVENT)) {
  31.             start();
  32.         } else if (event.getType().equals(Lifecycle.STOP_EVENT)) {
  33.             stop();
  34.         }
  35.     }
  36. }
  37. COPY// LifecycleBase.startInternal
  38. this.state = state;
  39. String lifecycleEvent = state.getLifecycleEvent();
  40. if (lifecycleEvent != null) {
  41.     fireLifecycleEvent(lifecycleEvent, data);
  42. }
  43. protected void fireLifecycleEvent(String type, Object data) {
  44.     LifecycleEvent event = new LifecycleEvent(this, type, data);
  45.     for (LifecycleListener listener : lifecycleListeners) {
  46.         listener.lifecycleEvent(event);
  47.     }
  48. }
复制代码
模板方法

四个模板方法,由子类具体实现
  1. COPYprotected abstract void initInternal() throws LifecycleException;
  2. protected abstract void startInternal() throws LifecycleException;
  3. protected abstract void stopInternal() throws LifecycleException;
  4. protected abstract void destroyInternal() throws LifecycleException;
复制代码
总结

通过提供init、start、stop、destory方法,通过相应的模板方法【模板设计模式】,提供组件的统一生命周期的管理、事件调度。
本文由传智教育博学谷狂野架构师教研团队发布。
如果本文对您有帮助,欢迎关注和点赞;如果您有任何建议也可留言评论或私信,您的支持是我坚持创作的动力。
转载请注明出处!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

玛卡巴卡的卡巴卡玛

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表