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 = https://www.cnblogs.com/jiagooushi/p/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方法,通過相應的模板方法【模板設計模式】,提供組件的統一生命周期的管理、事件調度,
本文由
傳智教育博學谷狂野架構師教研團隊發布,如果本文對您有幫助,歡迎
關注和點贊;如果您有任何建議也可留言評論或私信,您的支持是我堅持創作的動力,轉載請注明出處!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/547760.html
標籤:Java
