並行部署 Tomcat 中的零停機 Web 應用程式升級
1. 概述
Apache Tomcat,簡稱Tomcat,是Jakarta Servlet規範的開源實作。它充當 Web 伺服器,接收 HTTP 或 WebSocket 請求並呼叫負責的 servlet 來處理請求。
在本教程中,我們將了解Tomcat 中的平行部署如何支援零停機 Web 應用程式升級。
2. Tomcat部署方式
我們可以透過兩種方式使用 Apache Tomcat 來為我們的 Web 應用程式提供服務。第一個選項將 Tomcat 程式嵌入到我們的 Java 應用程式本身。或者,我們可以將 Apache Tomcat 作為專用 Web 伺服器進程來運行,為一個或多個 Web 應用程式提供服務。在這種模式下,開發人員將Web應用程式打包成Web應用程式存檔(WAR)格式。然後,Web伺服器管理員將Web應用程式部署到Tomcat Web伺服器。
儘管不太流行,但為多個 Web 應用程式運行專用 Tomcat 進程可能會很有好處。例如,當我們在不同的 Web 應用程式之間共用相同的 Web 伺服器程序時,計算資源的使用將會更有效率。
當我們將 Tomcat 作為專用 Web 伺服器進程運行時,我們需要學習如何對正在運行的 Web 應用程式進行零停機重新部署。與容器化 Web 應用程式通常將此任務委託給 Kubernetes 等外部編排器相反, Tomcat 中的部署依賴 Tomcat 伺服器來最大限度地減少 Web 應用程式升級的停機時間。
3. 並行部署,實現零停機重新部署
在 Apache Tomcat 版本 7 之前,重新部署正在執行的 Web 應用程式會造成破壞。具體來說,我們需要重新啟動 Tomcat 伺服器以重新部署現有的正在運行的 Web 應用程式。這是不可取的,因為它會在重新部署 Web 應用程式時引入停機時間。此外,重新啟動還會中斷同一 Tomcat 執行個體中執行的其他 Web 應用程式。
幸運的是, Apache Tomcat 從版本 7 開始引入了平行部署機制,以支援 Web 應用程式的零停機重新部署。
3.1.版本化部署
Apache Tomcat 中的平行部署功能使我們能夠在不停機的情況下重新部署 Web 應用程式。我們使用雙哈希運算子 (##) 對部署進行版本控制以啟用並行部署。具體來說,我們需要透過在檔案名稱副檔名前加上##{version}來對 WAR 檔案進行版本控制。例如,讓我們將demo.war檔案部署版本升級為版本 1:
$ mv demo.war demo##1.war
值得注意的是,檔案名稱中的版本資訊不會影響 Tomcat 為 Web 應用程式提供服務的上下文路徑。在上面的範例中, demo##1.war部署仍將在/demo上下文路徑下提供服務。
稍後,當我們想要升級 Web 應用程式時,我們將部署另一個具有不同版本號的 WAR 文件,例如demo##2.war 。
3.2.優雅升級
透過版本化部署,具有不同版本號的相同 Web 應用程式的任何後續部署都會觸發並行部署。具體來說,Tomcat啟動新版本的Web應用程式。然後,它逐漸將流量路由到與最新版本相同的上下文路徑。重要的是,在此過程中它仍然運行舊版本。這可確保舊版本提供的任何現有流量不會受到干擾。
最終,所有流量都將路由到新版本的 Web 應用程式。那時,我們可以停用舊的部署。
4. 演示並行部署
為了查看 Apache Tomcat 並行部署的實際效果,我們首先設定一個 Tomcat Web 伺服器。然後,我們將部署 Web 應用程式的第一個版本web-v1.war 。隨後,我們將使用web-v2.war檔案執行升級,並看到兩個 Web 應用程式同時運行。
4.1.安裝並執行 Apache Tomcat 伺服器
首先,我們需要安裝 Tomcat 軟體。我們將從其官方網站下載 Apache Tomcat 版本 10 軟體包,然後透過將整個 ZIP 檔案解壓縮到工作目錄中來安裝它:
$ wget -qO apache-tomcat-10.zip https://dlcdn.apache.org/tomcat/tomcat-10/v10.1.24/bin/apache-tomcat-10.1.24.zip
$ unzip apache-tomcat-10.zip
然後,我們可以透過執行bin/catalina.sh中的start指令來啟動 Tomcat 伺服器:
$ ./apache-tomcat-10.1.24/bin/catalina.sh start
Using CATALINA_BASE: /opt/tomcat-10/apache-tomcat-10.1.24
...
Tomcat started.
此時,我們的 Tomcat 伺服器將啟動並運行。我們可以透過向localhost的連接埠8080發送 HTTP GET 請求來驗證它,並看到我們傳回了預設的 Tomcat 歡迎頁面:
$ curl http://localhost:8080
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Apache Tomcat/10.1.24</title>
...
4.2.建立範例 Web 應用程式
出於演示目的,我們將使用同一 Web 應用程式的兩個不同版本: demo-v1.war和demo-v2.war 。它是一個 Spring Boot 應用程序,可充當/home處的單一 GET 端點。終端返回一條文字訊息Hello world – version N其中N對應版本號。這有助於我們可視化正在互動的 Web 應用程式的版本。
建立 WAR 檔案超出了本應用程式的範圍,但我們有一篇單獨的文章深入討論如何將 Web 應用程式打包到 WAR 檔案。
4.3.初始部署
讓我們部署我們的 Web 應用程式並將我們的第一個部署版本設為版本 1 :
$ cp target/demo-v1.war /opt/apache-tomcat-10.1.24/webapps/demo##1.war
在上面的命令中,我們透過將 WAR 檔案複製到 Tomcat 實例的webapps目錄來部署 Web 應用程式demo-v1.war 。重要的是,我們將 WAR 檔案重新命名為demo##1以對其進行版本控制。我們可以透過向/home路徑發出curl指令來驗證部署是否成功:
$ curl http://localhost:8080/demo/home
Hello world - version 1
4.4.推出新版本
讓我們透過將demo-v2.war檔部署到 Tomcat Web 伺服器來升級我們的 Web 應用程式。我們將使用相同的cp命令將檔案複製到webapps目錄並將版本資訊新增至名稱:
$ cp target/demo-v2.war /opt/apache-tomcat-10.1.24/webapps/demo##2.war
如果我們重複執行curl命令,我們將看到伺服器在升級過程中繼續回應我們對GET /home的請求:
$ curl http://localhost:8080/demo/home
Hello world - version 1
$ curl http://localhost:8080/demo/home
Hello world - version 1
...
不久之後,我們將看到新版本正在滿足我們的請求:
$ curl http://localhost:8080/demo/home
Hello world - version 2
5. 結論
在本教程中,我們了解了 Apache Tomcat 是一個 Web 伺服器,為打包為 WAR 檔案的 Web 應用程式提供服務。然後,我們強調了在重新部署時最大限度地減少 Tomcat 伺服器的停機時間非常重要。隨後,我們了解到 Apache Tomcat 版本 7 及更高版本具有平行部署機制,可讓我們執行零停機 Web 應用程式升級。
最後,我們使用一個工作範例示範了並行部署的工作原理。我們也看到並行部署可確保服務的現有流量不會中斷。