1. 程式人生 > >知識小罐頭08(tomcat8啟動源碼分析 上)

知識小罐頭08(tomcat8啟動源碼分析 上)

監聽 count gen 分享圖片 要花 實例化 重要 進行 int

  前面好幾篇都說的是一個請求是怎麽到servlet中的service方法的,這一篇我們來看看Tomcat8是怎麽啟動並且初始化其中的組件的?

  相信看了前面幾篇的小夥伴應該對Tomcat中的各個組件不陌生了,所以我們就可以加快一點速度;

  簡單說一下Tomcat啟動流程,首先是設置一下各種類加載器,然後加載server.xml配置文件,然後初始化Container各個容器,最後就是連接器Connector。

1.批處理文件  

  雙擊startup.bat文件啟動tomcat,其實內部就是跳轉到catalina.bat文件(.bat文件時windows系統用的,那些.sh配置文件是Unix、Linux系統使用的)

技術分享圖片

  startup.bat文件內部其實就是一些指令從上到下順序執行,作用是進行一些目錄的判斷,並找到catalina.bat文件的位置,如下圖所示

技術分享圖片

  註意:.bat文件其實就是一個批處理文件,裏面一條條的命令都有自己獨特的語法,你知需要百度“startup.bat詳解”可以看到很多博客,其實就我感覺很像mysql的觸發器吧,裏面封裝了很多命令,有自己獨特的語法,只要一觸發就會一連串的執行,這裏就不多說,不是我們的重點,用到的時候再去仔細研究,這裏粗略提一下。

 

   我們再看看catalina.bat文件 

技術分享圖片

  由於tomcat是用java語言開發出來的,所以啟動Tomcat本質上就是運行一個java程序的main方法,然後後續就會初始化一系列的東西。

2.看看Bootstrap類的main方法

  我們就看看main方法內核心部分,在下圖中標識了三步:

技術分享圖片

技術分享圖片

  總結一下,main方法內部核心就是創建一個Bootstrap對象,然後調用這個對象的init、load、start方法,看名字就應該大概猜出一點東西了:

  init:大概是初始化一些類加載器什麽的;

  load:應該是加載什麽配置文件,還記得我說過最重要的配置文件是哪個嗎?對,就是server.xml文件,其實就是加載這個文件;

  start:內部差不多初始化完了所有的容器和連接器,等待連接;

  我們分別對這三個方法加斷點進行調試,理解其中的原理之後整個Tomcat的啟動流程也就清楚了!

3.init方法

  還是只看核心的邏輯,至於怎麽實例化類加載器和設置類加載器,感興趣的小夥伴就自己去研究走走源碼。

技術分享圖片

技術分享圖片

4.load方法

  通過看源碼,其實可以看到Bootstrap的load方法,就是通過反射調用Catalina的load方法

技術分享圖片

技術分享圖片

  我們斷點進入最後的那個invoke方法,看看Catalina的load方法是加載了些什麽東西

技術分享圖片

  這個Digester就是為了解析servler.xml定義了很多的解析規則,真要搞懂這個東西,肯定要花一定的時間去好好研究的;

  我們在這裏簡單而隨意看幾個我們熟悉的東西,具體的解析過程肯定要自己去了解的;

技術分享圖片

技術分享圖片

技術分享圖片

技術分享圖片

  這個Digester是了解servler.xml具體解析規則必要的東西,我們把規則已經指定好了,下一步肯定就是加載server.xml文件了

技術分享圖片

技術分享圖片

技術分享圖片

  準備好了Digester和server.xml的流之後,然後底層用SAX去解析這個xml文件(註意,前面只是解析出來了server.xml中的各個組件對應的類名以及組件之間的父子關系, 沒有實例化,到parse方法才真正實例化

技術分享圖片

   接著我們就要去把一些需要用到的容器進行一些初始化設置,更方便我們使用!

技術分享圖片

  從這裏開始我們就會看到一個類似多米諾骨牌效應的這麽一個現象,一個接一個的初始化,而且這裏涉及到了一個知識點叫做JMX,有關於這個JMX(Java Management Extensions),我查了很多的資料,網上復制粘貼的一大堆,看得很亂,雖然我沒有怎麽仔細的去研究,但是大概的邏輯我是知道了,下面就簡單的說說;

5.JMX的簡介和事件監聽

  便於理解,JMX可以想象成工商局,每家公司必須要向工商局註冊自己,這個時候工商局就對每一家公司都有了管理的權利,無論是哪一家公司要改名字,要合並,註銷等等,都必須經過工商局的的同意,工商局還能對一些非法公司進行整改什麽的,可以說工商局就是管理了每一家公司的生命周期,可以對每家公司進行監控符合管理。

  對應在Tomcat中,我們必須要把Tomcat中的所有組件(在這裏叫做MBean,類似spring容器中叫做bean)給註冊到一個叫做Registry的地方,Registry就是基於JMX搞出來的一個東西,然後我們執行所有組件的init,start方法,都可以在JMX中找到對應的MBean執行對應的init、start方法;這裏也只是稍微提一下JMX,內容很多一下子說不完,最好自己多查查資料看看。

技術分享圖片

技術分享圖片

  JMX的結構圖找了好久,終於看到一個圖比較滿意的,進行一些小小的修改,如下所示:

  Agent Layer(代理層):主要包括Agent Services中幾個服務(計時器、監控、動態加載MBean、關系服務),還有MBean Server兩部分組成

  Distributed layer(分布層):包含一些比較厲害的組件,其實我感覺就類似可視化工具,可以很方便的對那些MBean進行一些管理和修改。

  還有在MBean Server中的多個MBean組成一個Instrumentation Layer(指示層),這個就沒啥說的;總之,JMX我用得不是很多,需要真正用到的時候再慢慢研究吧,哈哈!

  感興趣的小夥伴可以自己研究這個寫幾個HelloWorldMBean試試就ok了

技術分享圖片

  

  再說說事件監聽,事件監聽又是一個什麽鬼呢?不準確的來說,在Tomcat啟動的時候會有個全局事件(就類似一個全局變量),很多的監聽器會時時刻刻監聽這個全局事件,當對一個組件進行一些操作(會修改狀態碼state),那麽這個全局事件就會變化,遍歷所有監聽器執行某方法,下面就隨便看看這個全局事件:

技術分享圖片

技術分享圖片

技術分享圖片

還記得最前面的server.xml配置文件的<server>中配置的很多監聽器嗎?其實就是配合這個全局事件起作用的(看英文應該翻譯成生命周期事件吧。。。)

6.接第4步繼續

  這裏一定要理清楚一個邏輯,Tomcat中所有組件都必須是LifecycleBase的子類(其實都直接或者間接的繼承了LifecycleBase這個類),這個類就是所有組件的爸爸,假如這個爸爸有九個兒子,大兒子要給最小的兒子一顆糖,你就會看到一個很有趣很坑爹的現象:大兒子-------->爸爸---------->二兒子--------->爸爸--------->三兒子---------->爸爸---------->四兒子---------->.......------->爸爸------->最小的兒子!

  這樣糖才能到最小的兒子手裏,是不是真的很坑爹,哈哈!

  所以我們在Tomcat也可以看到一個這樣的邏輯:

  server.init()---------->LifecycleBase.init(), 在init()方法內部就會執行initInternal()方法,並改變全局事件------------->service.init()方法------------>LifecycleBase.init(),執行initInternal()方法,並改變全局事件--------->connector.init()和engine.init()---------->LifecycleBase.init()。。。。。後面都是這個邏輯,幾乎一模一樣,初始化之後啟動start()的邏輯也是這個,所以這個邏輯一定要搞清楚,搞清楚這個了後面就沒難度了。

  下面我們就簡單看看一些關鍵的地方,由於絕大部分都是相同的,就不一一截圖了;

技術分享圖片

  看看initInternal()方法內部:

技術分享圖片

技術分享圖片

技術分享圖片

  一直往下看,我們看看StandardService中的initInternal()方法:

技術分享圖片

技術分享圖片

  engine的初始化是在看不出來什麽有趣的東西,我們就重點看看HTTP連接器的初始化的關鍵代碼:

技術分享圖片

技術分享圖片

  【省略很多重復步驟】

技術分享圖片

  【省略很多重復步驟】

  這個是Tomcat的NIO連接,其中addr=0.0.0.0/0.0.0.0:8080;acceptCount = 100;看這個就知道監聽8080端口,默認並發連接數100個,這個可以自己根據實際情況設置

技術分享圖片

技術分享圖片

  到這裏Tomcat啟動初始化的步驟算是結束了,內容看起來比較多,但是思路自我感覺還是比較清晰的,了解JMX和事件監聽的相關知識之後,還是比較容易的,不過強調一點,一定要自己走走源碼,加深理解!

  這篇說的東西不多,就是初始化了幾乎所有組件,就好像一個廚師,把所有的菜都洗好並且切好、分類、分盤,調料也準備就緒,下一步,就是開始做出美味的菜肴了。

  下一篇我們簡單看看Tomcat的start過程。

知識小罐頭08(tomcat8啟動源碼分析 上)