熱加載和熱部署,沒聽過?看看 Tomcat 是怎麼實現的


熱加載和熱部署,沒聽過?看看 Tomcat 是怎麼實現的

作者 | 不學無數的程序員

來源 | https://urlify.cn/Ir6Z7n


熱部署就是在服務器運行時重新部署項目,熱加載即在在運行時重新加載class,從而升級應用。

通常情況下在開發環境中我們使用的是熱加載,因為熱加載的實現的方式在Web容器中啟動一個後臺線程,定期檢測相關文件的變化,如果有變化就重新加載類,這個過程不會清空Session。而在生產環境我們一般應用的是熱部署,熱部署也是在Web應用後臺線程定期檢測,發現有變化就會重新加載整個Web應用,這種方式更加徹底會清空Session。

熱加載

熱加載其實我們在開發過程中經常使用,例如我們使用Idea開發時,我們在設置頁面可以進行設置,當修改文件時,我們可以選擇不重啟項目,選擇重新加載此文件。而在Tomcat中也能設置,Tomcat默認情況下是不開啟熱加載的。需要在Tomcat路徑下的Context.xml中配置reloadable參數來開啟這個功能。

熱加載和熱部署,沒聽過?看看 Tomcat 是怎麼實現的

我們演示一下Tomcat是如何熱加載的。在webapp下我們新建了一個項目,裡面的Servlet文件如下

熱加載和熱部署,沒聽過?看看 Tomcat 是怎麼實現的

目錄結構如下

熱加載和熱部署,沒聽過?看看 Tomcat 是怎麼實現的

為了演示Tomcat運行時能修改class文件能夠動態加載。我們分為以下三步

  1. 正常啟動Tomcat。輸入http://localhost:8080/mywebapp/myservlet,觀察頁面輸出
  2. 在Tomcat啟動的情況下修改MyServlet文件後覆蓋原來的class文件
  3. 再次觀察頁面情況。觀察頁面輸出是否修改

下面直接用動態圖演示效果,更直觀一些。


熱加載和熱部署,沒聽過?看看 Tomcat 是怎麼實現的

我們可以看到在Tomcat運行的情況下,直接替換class文件是能夠直接生效的。那麼Tomcat是如何做到的呢?其實我們可以自己推導一下。

  1. 所有的class文件都是交由類加載來管理的
  2. 如果換了class文件是不是隻需要更換相應的類加載器重新加載就行

那麼接下來我們來驗證我們的結論,看一下在Tomcat中是如何實現熱加載的。Tomcat要監聽class文件是否變化應該是新起了一個線程來觀測。那麼看到在Context的啟動方法中,看到調用了threadStart的方法。

熱加載和熱部署,沒聽過?看看 Tomcat 是怎麼實現的

其中在後臺開啟週期性的任務,使用了Java提供的ScheduledThreadPoolExecutor。除了能週期性執行任務以外還有線程池的功能。上面代碼中調用了scheduleWithFixedDelay方法,第一個傳入的參數就是要執行的任務。我們接下來看任務類ContainerBackgroundProcessor是如何實現的。

熱加載和熱部署,沒聽過?看看 Tomcat 是怎麼實現的

上面代碼中我們可以知道具體的後臺監聽代碼是在backgroundProcess方法中實現的。那麼我們看Context容器的backgroundProcess方法是如何實現的。

熱加載和熱部署,沒聽過?看看 Tomcat 是怎麼實現的

進去loader.backgroundProcess();中我們可以看到

熱加載和熱部署,沒聽過?看看 Tomcat 是怎麼實現的

我們可以發現Tomcat熱加載的步驟

  1. 如果發現有文件發生變化,熱加載開關開啟
  2. 關閉Context容器
  3. 重啟Context容器

在這個過程中,最重要的部分其實就是類加載器了。因為一個Context容器對應一個類加載器。所以在銷燬Context容器的時候也連帶著將其類加載器一併銷燬了。Context在重啟的過程中也會創建新的類加載器來加載我們新建的文件。

熱部署

如果還是不懂熱部署是什麼的,下面演示一遍應該就明白了。Tomcat在啟動的時候會將其目錄下webapp中war包解壓後然後封裝為一個Context供外部訪問。那麼熱部署就是在程序運行時,如果我們修改了War包中的東西。那麼Tomcat就會刪除之前的War包解壓的文件夾,重新解壓新的War包。


熱加載和熱部署,沒聽過?看看 Tomcat 是怎麼實現的

我們發現上面動圖中在Tomcat運行時,我們修改了War包的信息,它就會將原來的刪除然後重新生成一份。

我們從上面的動圖中其實就看出了熱部署和熱加載的區別了。熱部署是將文件夾刪除然後重新解壓包。那麼熱加載是由Context容器負責的。那麼熱部署又是由哪個容器負責呢?因為一個文件夾對應一個Context。既然文件夾都刪除了,那麼肯定不是由Context容器負責了。那麼應該就是Context的父容器Host來負責。

我們可以看到Host容器並沒有實現自己的backgroundProcess方法。那麼它是如何監聽的呢?既然它沒有實現方法,肯定是調用了父類的backgroundProcess方法。我們可以看到在父類的backgroundProcess中

熱加載和熱部署,沒聽過?看看 Tomcat 是怎麼實現的

可以看到週期事件的監聽器。而Host的事件監聽器是HostConfig類的lifecycleEvent方法

熱加載和熱部署,沒聽過?看看 Tomcat 是怎麼實現的

我們可以看check方法

熱加載和熱部署,沒聽過?看看 Tomcat 是怎麼實現的

熱部署的步驟其實也可以簡化為三步驟

  1. 檢查Host管理下的所有web應用
  2. 如果原來的Web應用被刪除,就將相應Context容器刪除
  3. 如果有新War包放進來,就部署相應的War包


分享到:


相關文章: