建議:html
畢竟TOMCAT的框架仍是比較複雜的, 單是從文字上理解, 是不那麼容易掌握TOMCAT的框架的。 因此得實踐、實踐、再實踐。 建議下載一份TOMCAT的源碼, 調試經過, 而後單步跟蹤其啓動過程。 若是有不明白的地方, 再來查閱本文, 看是否能獲得幫助。 我相信這樣效果以及學習速度都會好不少!
1. Tomcat的總體框架結構
Tomcat的基本框架, 分爲4個層次。
Top Level Elements:
Server
Service
Connector
HTTP
AJP
Container
Engine
Host
Context
Component
manager
logger
loader
pipeline
valve
...
站在框架的頂層的是Server和Service
Server: 其實就是BackGroud程序, 在Tomcat裏面的Server的用處是啓動和監聽服務端事件(諸如重啓、關閉等命令。 在tomcat的標準配置文件:server.xml裏面, 咱們能夠看到「」這裏的"SHUTDOWN"就是server在監聽服務端事件的時候所使用的命令字)
Service: 在tomcat裏面, service是指一類問題的解決方案。 一般咱們會默認使用tomcat提供的:Tomcat-Standalone 模式的service。 在這種方式下的service既給咱們提供解析jsp和servlet的服務, 同時也提供給咱們解析靜態文本的服務。
Connector: Tomcat都是在容器裏面處理問題的, 而容器又到哪裏去取得輸入信息呢?
Connector就是專幹這個的。 他會把從socket傳遞過來的數據, 封裝成Request, 傳遞給容器來處理。
一般咱們會用到兩種Connector,一種叫http connectoer, 用來傳遞http需求的。 另外一種叫AJP, 在咱們整合apache與tomcat工做的時候, apache與tomcat之間就是經過這個協議來互動的。 (說到apache與tomcat的整合工做, 一般咱們的目的是爲了讓apache 獲取靜態資源, 而讓tomcat來解析動態的jsp或者servlet。)
Container: 當http connector把需求傳遞給頂級的container: Engin的時候, 咱們的視線就應該移動到Container這個層面來了。
在Container這個層, 咱們包含了3種容器: Engin, Host, Context.
Engin: 收到service傳遞過來的需求, 處理後, 將結果返回給service( service 是經過 connector 這個媒介來和Engin互動的 ).
Host: Engin收到service傳遞過來的需求後,不會本身處理, 而是交給合適的Host來處理。
Host在這裏就是虛擬主機的意思, 一般咱們都只會使用一個主機,既「localhost」本地機來處理。
Context: Host接到了從Host傳過來的需求後, 也不會本身處理, 而是交給合適的Context來處理。
好比:
前者交給foo這個Context來處理, 後者交給bar這個Context來處理。
很明顯吧! context的意思其實就是一個web app的意思。
咱們一般都會在server.xml裏面作這樣的配置
這個context容器,就是用來幹咱們該乾的事兒的地方的。
Compenent: 接下來, 咱們繼續講講component是幹什麼用的。
咱們得先理解一下容器和組件的關係。
需求被傳遞到了容器裏面, 在合適的時候, 會傳遞給下一個容器處理。
而容器裏面又盛裝着各類各樣的組件, 咱們能夠理解爲提供各類各樣的增值服務。
manager: 當一個容器裏面裝了manager組件後,這個容器就支持session管理了, 事實上在tomcat裏面的session管理, 就是靠的在context裏面裝的manager component.
logger: 當一個容器裏面裝了logger組件後, 這個容器裏所發生的事情, 就被該組件記錄下來啦! 咱們一般會在logs/ 這個目錄下看見 catalina_log.time.txt 以及 localhost.time.txt 和localhost_examples_log.time.txt。 這就是由於咱們分別爲:engin, host以及context(examples)這三個容器安裝了logger組件, 這也是默認安裝, 又叫作標配 :)
loader: loader這個組件一般只會給咱們的context容器使用, loader是用來啓動context以及管理這個context的classloader用的。
pipline: pipeline是這樣一個東西, 當一個容器決定了要把從上級傳遞過來的需求交給子容器的時候, 他就把這個需求放進容器的管道(pipeline)裏面去。 而需求傻呼呼得在管道里面流動的時候, 就會被管道里面的各個閥門攔截下來。 好比管道里面放了兩個閥門。 第一個閥門叫作「access_allow_vavle」, 也就是說需求流過來的時候,它會看這個需求是哪一個IP過來的, 若是這個IP已經在黑名單裏面了, sure, 殺! 第二個閥門叫作「defaul_access_valve」它會作例行的檢查, 若是經過的話,OK, 把需求傳遞給當前容器的子容器。 就是經過這種方式, 需求就在各個容器裏面傳遞,流動, 最後抵達目的地的了。
valve: 就是上面所說的閥門啦。
Tomcat裏面大概就是這麼些東西, 咱們能夠簡單地這麼理解tomcat的框架,它是一種自上而下, 容器裏又包含子容器的這樣一種結構。java
2. Tomcat的啓動流程
這篇文章是講tomcat怎麼啓動的,既然咱們大致上瞭解了TOMCAT的框架結構了, 那麼咱們能夠望文生意地就猜到tomcat的啓動, 會先啓動父容器,而後逐個啓動裏面的子容器。 啓動每個容器的時候, 都會啓動安插在他身上的組件。 當全部的組件啓動完畢, 全部的容器啓動完畢的時候, tomcat自己也就啓動完畢了。
瓜熟蒂落地, 咱們一樣能夠猜到, tomcat的啓動會分紅兩大部分, 第一步是裝配工做。 第二步是啓動工做。
裝配工做就是爲父容器裝上子容器, 爲各個容器安插進組件的工做。 這個地方咱們會用到digester模式, 至於digester模式什麼, 有什麼用, 怎麼工做的. 請參考
啓動工做是在裝配工做以後, 一旦裝配成功了, 咱們就只須要點燃最上面的一根導線, 整個tomcat就會被激活起來。 這就比如咱們要開一輛已經裝配好了的汽車的時候同樣,咱們只要把鑰匙插進鑰匙孔,一擰,汽車的引擎就會發動起來,空調就會開起來, 安全裝置就會生效, 如此一來,汽車整個就發動起來了。(這個過程確實和TOMCAT的啓動過程不謀而和, 讓咱們不得不懷疑 TOMCAT的設計者是在GE作JAVA開發的)。
2.1 一些有意思的名稱:
Catalina
Tomcat
Bootstrap
Engin
Host
Context
他們的意思頗有意思:
Catalina: 遠程轟炸機
Tomcat: 熊貓轟炸機 -- 轟炸機的一種(這讓我想起了讓國人引覺得豪的熊貓手機,是否是英文能夠叫作tomcat??? , 又讓我想起了另外一則廣告: 波導-手機中的戰鬥機、波音-客機中的戰鬥機 )
Bootstap: 引導
Engin: 發動機
Host: 主機,領土
Context: 內容, 目標, 上下文
... 在許多許多年後, 現代人類已經滅絕。 後現代生物發現了這些單詞零落零落在一塊。 一個自覺得聰明的傢伙把這些東西翻譯出來了:
在地勤人員的引導(bootstrap)下, 一架轟炸架(catalina)騰空躍起, 遠看是熊貓轟炸機(tomcat), 近看仍是熊貓轟炸機! 憑藉着優秀的發動機技術(engin), 這架熊貓轟炸機飛臨了敵國的領土上空(host), 對準目標(context)投下了毀天滅地的核彈頭,波~ 現代生物就這麼隔屁了~
2.2 tomcat的啓動就是從org.apache.catalina.startup.Bootstrap這個類悍然啓動的!
在Bootstrap裏作了兩件事:
1. 指定了3種類型classloader:
commonLoader: common/classes、common/lib、common/endorsed
catalinaLoader: server/classes、server/lib、commonLoader
sharedLoader: shared/classes、shared/lib、commonLoader
2. 引導Catalina的啓動。
用Reflection技術調用org.apache.catalina.startup.Catalina的process方法, 並傳遞參數過去。
2.3 Catalina.java
Catalina完成了幾個重要的任務:
1. 使用Digester技術裝配tomcat各個容器與組件。
1.1 裝配工做的主要內容是安裝各個大件。 好比server下有什麼樣的servcie。 Host會容納多少個context。 Context都會使用到哪些組件等等。
1.2 同時呢, 在裝配工做這一步, 還完成了mbeans的配置工做。 在這裏,我簡單地但不十分精確地描述一下mbean是什麼,幹什麼用的。
咱們本身生成的對象, 本身管理, 天經地義! 可是若是咱們建立了對象了, 想讓別人來管, 怎麼辦呢? 我想至少得告訴別人咱們都有什麼, 以及經過什麼方法能夠找到 吧! JMX技術給咱們提供了一種手段。 JMX裏面主要有3種東西。Mbean, agent, connector.
Mbean: 用來映射咱們的對象。也許mbean就是咱們建立的對象, 也許不是, 但有了它, 就能夠引用到咱們的對象了。
Agent: 經過它, 就能夠找到mbean了。
Connector: 鏈接Agent的方式。 能夠是http的, 也能夠是rmi的,還能夠直接經過socket。
發生在tomcat 裝配過程當中的事情: GlobalResourcesLifecycleListener 類的初始化會被觸發:
protected static Registry registry = MBeanUtils.createRegistry(); 會運行web