tomcat 源碼分析(三)基于JMX的生命周期管理

根據(jù)tomcat中server.xml文件解析出來的各個對象比如:Server哀军、Service沉眶、Connector等。這些容器都具有新建杉适、初始化完成沦寂、啟動、停止淘衙、失敗传藏、銷毀等狀態(tài)。tomcat的實現(xiàn)提供了對這些容器的生命周期管理彤守,深入剖析這一過程

生命周期類接口設(shè)計類圖如下:


涉及到的類的簡單介紹:

Lifecycle:定義了容器生命周期毯侦、容器狀態(tài)轉(zhuǎn)換及容器狀態(tài)遷移事件的監(jiān)聽器注冊和移除等主要接口;

LifecycleBase:作為Lifecycle接口的抽象實現(xiàn)類具垫,運用抽象模板模式將所有容器的生命周期及狀態(tài)轉(zhuǎn)換銜接起來侈离,此外還提供了生成LifecycleEvent事件的接口;

LifecycleSupport:提供有關(guān)LifecycleEvent事件的監(jiān)聽器注冊筝蚕、移除卦碾,并且使用經(jīng)典的監(jiān)聽器模式,實現(xiàn)事件生成后觸打監(jiān)聽器的實現(xiàn)起宽;

MBeanRegistration:JmxEnabled 的父類洲胖, jmx框架提供的注冊MBean的接口,引入此接口是為了便于使用JMX提供的管理功能坯沪;

LifecycleMBeanBase:Tomcat提供的對MBeanRegistration的抽象實現(xiàn)類绿映,運用抽象模板模式將所有容器統(tǒng)一注冊到JMX;

ContainerBase、StandardServer叉弦、StandardService丐一、WebappLoader、Connector淹冰、StandardContext库车、StandardEngine、StandardHost樱拴、StandardWrapper等容器都繼承了LifecycleMBeanBase柠衍,因此這些容器都具有了同樣的生命周期并可以通過JMX進行管理。

Tomcat 容器的組成:

StandardServer疹鳄、StandardService拧略、Connector芦岂、StandardContext這些容器瘪弓,彼此之間都有父子關(guān)系,每個容器都可能包含零個或者多個子容器如下:

Tomcat 容器狀態(tài):

NEW:容器剛剛創(chuàng)建時禽最,即在LifecycleBase實例構(gòu)造完成時的狀態(tài)腺怯。

INITIALIZED:容器初始化完成時的狀態(tài)。

STARTING_PREP:容器啟動前的狀態(tài)川无。

STARTING:容器啟動過程中的狀態(tài)呛占。

STARTED:容器啟動完成的狀態(tài)。

STOPPING_PREP:容器停止前的狀態(tài)懦趋。

STOPPING:容器停止過程中的狀態(tài)晾虑。

STOPPED:容器停止完成的狀態(tài)。

DESTROYED:容器銷毀后的狀態(tài)仅叫。

FAILED:容器啟動帜篇、停止過程中出現(xiàn)異常的狀態(tài)。

MUST_STOP:此狀態(tài)未使用诫咱。

MUST_DESTROY:此狀態(tài)未使用笙隙。

這些狀態(tài)都定義在枚舉類LifecycleState中。

事件與監(jiān)聽

每個容器由于繼承自LifecycleBase坎缭,當(dāng)容器狀態(tài)發(fā)生變化時竟痰,都會調(diào)用fireLifecycleEvent方法,生成LifecycleEvent掏呼,并且交由此容器的事件監(jiān)聽器處理坏快。LifecycleBase的fireLifecycleEvent方法的實現(xiàn)見代碼一:

LifecycleSupport的實現(xiàn)如下見代碼二:

將事件通知給所有監(jiān)聽當(dāng)前容器的生命周期監(jiān)聽器LifecycleListener,并調(diào)用LifecycleListener的lifecycleEvent方法憎夷。每個容器都維護這一個監(jiān)聽器緩存假消,其實現(xiàn)如下見代碼三:

每個容器在新建、初始化岭接、啟動富拗,銷毀臼予,被添加到父容器的過程中都會調(diào)用父類LifecycleBase的addLifecycleListener方法,addLifecycleListener的實現(xiàn)見代碼如見代碼四:

LifecycleBase的addLifecycleListener方法實際是對LifecycleSupport的addLifecycleListener方法的簡單代理啃沪,LifecycleSupport的addLifecycleListener方法的實現(xiàn)粘拾,見代碼五:

在代碼清單2中,我們講過容器會最終調(diào)用每個對此容器感興趣的LifecycleListener的lifecycleEvent方法创千,那么LifecycleListener的lifecycleEvent方法會做些什么呢缰雇?為了簡單起見,我們以監(jiān)聽器AprLifecycleListener為例追驴,AprLifecycleListener的lifecycleEvent方法的實現(xiàn)械哟,見代碼六:

容器生命周期

每個容器都會有自身的生命周期,其中也涉及狀態(tài)的遷移殿雪,以及伴隨的事件生成暇咆,本節(jié)詳細介紹Tomcat中的容器生命周期實現(xiàn)。所有容器的轉(zhuǎn)態(tài)轉(zhuǎn)換(如新疆丙曙、初始化爸业、啟動、停止等)都是由外到內(nèi)亏镰,由上到下進行扯旷,即先執(zhí)行父容器的狀態(tài)轉(zhuǎn)換及相關(guān)操作,然后再執(zhí)行子容器的轉(zhuǎn)態(tài)轉(zhuǎn)換索抓,這個過程是層層迭代執(zhí)行的钧忽。

容器新建

所有容器在構(gòu)造的過程中,都會首先對父類LifecycleBase進行構(gòu)造逼肯。LifecycleBase中定義了所有容器的起始狀態(tài)為LifecycleState.NEW耸黑;

容器的初始化過程

所說的具體容器,實際就是LifecycleBase的具體實現(xiàn)類汉矿,目前LifecycleBase的類繼承體系崎坊;

LifecycleBase的類繼承體系

我們對Tomcat的源碼進行分析,其處理步驟如下:

調(diào)用方調(diào)用容器父類LifecycleBase的init方法洲拇,LifecycleBase的init方法主要完成一些所有容器公共抽象出來的動作奈揍;

LifecycleBase的init方法調(diào)用具體容器的initInternal方法實現(xiàn),此initInternal方法用于對容器本身真正的初始化赋续;

具體容器的initInternal方法調(diào)用父類LifecycleMBeanBase的initInternal方法實現(xiàn)男翰,此initInternal方法用于將容器托管到JMX,便于運維管理纽乱;

LifecycleMBeanBase的initInternal方法調(diào)用自身的register方法蛾绎,將容器作為MBean注冊到MBeanServer;

容器如果有子容器,會調(diào)用子容器的init方法租冠;

容器初始化完畢鹏倘,LifecycleBase會將容器的狀態(tài)更改為初始化完畢,即LifecycleState.INITIALIZED顽爹。

對容器初始化LifecycleBase的源碼進行分析纤泵,init方法的實現(xiàn):

只有當(dāng)前容器的狀態(tài)處于LifecycleState.NEW的才可以被初始化,真正執(zhí)行初始化的方法是initInternal镜粤,當(dāng)初始化完畢捏题,當(dāng)前容器的狀態(tài)會被更改為LifecycleState.INITIALIZED。為了簡便起見肉渴,我們還是以StandardServer這個容器為例公荧,StandardServer的initInternal方法的實現(xiàn);

步驟一 ?將當(dāng)前容器注冊到JMX

StandServer調(diào)用直接父類LifecycleMBeanBase的initInternal方法,為當(dāng)前容器創(chuàng)建DynamicMBean同规,并注冊到JMX中循狰。

LifecycleMBeanBase的register方法會為當(dāng)前容器創(chuàng)建對應(yīng)的注冊名稱,以StandardServer為例捻浦,getDomain默認返回Catalina晤揣,因此StandardServer的JMX注冊名稱默認為Catalina:type=Server桥爽,真正的注冊在registerComponent方法中實現(xiàn)朱灿;

Registry的registerComponent方法會為當(dāng)前容器(如StandardServer)創(chuàng)建DynamicMBean,并且注冊到MBeanServer钠四;

步驟二將StringCache盗扒、MBeanFactory、globalNamingResources注冊到JMX缀去;其中StringCache的注冊名為Catalina:type=StringCache侣灶,MBeanFactory的注冊名為Catalina:type=MBeanFactory,globalNamingResources的注冊名為Catalina:type=NamingResources缕碎。

步驟三初始化子容器

從代碼中看到StandardServer主要對Service子容器進行初始化褥影,默認是StandardService。

注意:個別容器并不完全遵循以上的初始化過程咏雌,比如ProtocolHandler作為Connector的子容器凡怎,其初始化過程并不是由Connector的initInternal方法調(diào)用的,而是與啟動過程一道被Connector的startInternal方法所調(diào)用赊抖。

容器啟動

每個容器的start方法是自身啟動的入口统倒,其啟動過程對Tomcat的源碼進行分析,其處理步驟如下:

調(diào)用方調(diào)用容器父類LifecycleBase的start方法氛雪,LifecycleBase的start方法主要完成一些所有容器公共抽象出來的動作房匆;

LifecycleBase的start方法先將容器狀態(tài)改為LifecycleState.STARTING_PREP,然后調(diào)用具體容器的startInternal方法實現(xiàn),此startInternal方法用于對容器本身真正的初始化浴鸿;

具體容器的startInternal方法會將容器狀態(tài)改為LifecycleState.STARTING井氢,容器如果有子容器,會調(diào)用子容器的start方法啟動子容器岳链;

容器啟動完畢毙沾,LifecycleBase會將容器的狀態(tài)更改為啟動完畢,即LifecycleState.STARTED宠页。

除了初始化左胞、啟動外,各個容器還有停止和銷毀的生命周期举户,其原理與初始化烤宙、啟動類似有興趣的讀者可以自行研究

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市俭嘁,隨后出現(xiàn)的幾起案子躺枕,更是在濱河造成了極大的恐慌,老刑警劉巖供填,帶你破解...
    沈念sama閱讀 216,997評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拐云,死亡現(xiàn)場離奇詭異,居然都是意外死亡近她,警方通過查閱死者的電腦和手機叉瘩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來粘捎,“玉大人薇缅,你說我怎么就攤上這事≡苣ィ” “怎么了泳桦?”我有些...
    開封第一講書人閱讀 163,359評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長娩缰。 經(jīng)常有香客問我灸撰,道長,這世上最難降的妖魔是什么拼坎? 我笑而不...
    開封第一講書人閱讀 58,309評論 1 292
  • 正文 為了忘掉前任浮毯,我火速辦了婚禮,結(jié)果婚禮上演痒,老公的妹妹穿的比我還像新娘亲轨。我一直安慰自己,他們只是感情好鸟顺,可當(dāng)我...
    茶點故事閱讀 67,346評論 6 390
  • 文/花漫 我一把揭開白布惦蚊。 她就那樣靜靜地躺著器虾,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蹦锋。 梳的紋絲不亂的頭發(fā)上兆沙,一...
    開封第一講書人閱讀 51,258評論 1 300
  • 那天,我揣著相機與錄音莉掂,去河邊找鬼葛圃。 笑死,一個胖子當(dāng)著我的面吹牛憎妙,可吹牛的內(nèi)容都是我干的库正。 我是一名探鬼主播,決...
    沈念sama閱讀 40,122評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼厘唾,長吁一口氣:“原來是場噩夢啊……” “哼褥符!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起抚垃,我...
    開封第一講書人閱讀 38,970評論 0 275
  • 序言:老撾萬榮一對情侶失蹤喷楣,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后鹤树,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體铣焊,經(jīng)...
    沈念sama閱讀 45,403評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,596評論 3 334
  • 正文 我和宋清朗相戀三年罕伯,在試婚紗的時候發(fā)現(xiàn)自己被綠了曲伊。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,769評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡捣炬,死狀恐怖熊昌,靈堂內(nèi)的尸體忽然破棺而出绽榛,到底是詐尸還是另有隱情湿酸,我是刑警寧澤,帶...
    沈念sama閱讀 35,464評論 5 344
  • 正文 年R本政府宣布灭美,位于F島的核電站推溃,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏届腐。R本人自食惡果不足惜铁坎,卻給世界環(huán)境...
    茶點故事閱讀 41,075評論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望犁苏。 院中可真熱鬧硬萍,春花似錦、人聲如沸围详。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至买羞,卻和暖如春袁勺,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背畜普。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評論 1 269
  • 我被黑心中介騙來泰國打工期丰, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人吃挑。 一個月前我還...
    沈念sama閱讀 47,831評論 2 370
  • 正文 我出身青樓钝荡,卻偏偏與公主長得像,于是被迫代替她去往敵國和親舶衬。 傳聞我的和親對象是個殘疾皇子化撕,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,678評論 2 354

推薦閱讀更多精彩內(nèi)容