在台灣軟體開發的環境中,許多專案初期都採用單體架構,隨著業務發展和系統複雜度的提升,轉型到微服務架構的需求日益增長。本文以一個技術支援應用程式為例,逐步展示如何從單體架構遷移到微服務架構,並利用 Docker 容器化技術簡化佈署和管理流程。首先,我們會在現有的 Java 單體應用中新增一個 emailAddress 欄位,包含 POJO 模型的修改和 DAO 層的資料函式庫操作邏輯調整。接著,我們會比較單體應用和微服務架構在修改、佈署和擴充套件方面的差異,凸顯微服務架構的優勢,例如更容易處理錯誤、替換元件、採用新技術堆疊以及獨立擴充套件等。文章接著會探討 Docker 容器化技術,包含 Dockerfile 的撰寫、映像構建和佈署。Dockerfile 中包含了所有必要的環境設定,例如基礎映像選擇、Tomcat 安裝、WAR 檔案佈署和埠暴露等。最後,文章簡要介紹瞭如何使用 DC/OS 在 AWS 上快速設定 Mesos 和 Marathon 環境,並提到了在實際操作中可能遇到的網路組態、安全性以及效能調優等挑戰。
微服務遷移實戰研究:從單體架構到微服務
在現代軟體開發中,微服務架構已成為一種主流的設計模式。相比於傳統的單體架構,微服務架構能夠提供更高的靈活性、可擴充套件性和維護性。以下我們將透過一個具體的案例來探討從單體架構遷移到微服務架構的過程,並解析其帶來的好處。
新增新屬性至POJO(Plain Old Java Object)模型
首先,我們需要在Java模型中新增一個新的屬性,這裡以emailAddress為例:
@Component
private String emailAddress;
@XmlElement
public String getEmailAddress() {
return emailAddress;
}
public void setEmailAddress(String emailAddress) {
this.emailAddress = emailAddress;
}
內容解密:
- @Component:這是Spring框架中的註解,用於標記該類別為Spring管理的Bean。這樣可以讓Spring自動掃描並初始化該類別。
- @XmlElement:這是JAXB(Java Architecture for XML Binding)中的註解,用於將Java物件對映為XML元素。這樣可以在序列化和反序列化時自動處理
emailAddress屬性。 - getEmailAddress() 和 setEmailAddress():這是標準的Java Bean getter和setter方法,用於讀取和設定
emailAddress屬性。
在DAO層新增邏輯以取得資料函式庫屬性
接下來,我們需要在資料存取層(DAO)中新增邏輯以儲存該屬性到資料函式庫:
private String saveToDatabase(TicketRequest ticketRequest) {
// 與現有邏輯結合
ticket.setEmailAddress(ticketRequest.getEmailAddress());
}
內容解密:
- saveToDatabase():這是一個方法,用於將
TicketRequest物件中的資料儲存到資料函式庫中。 - ticket.setEmailAddress(ticketRequest.getEmailAddress()):這行程式碼從
ticketRequest物件中取得emailAddress屬性,並設定到ticket物件中。這樣可以確保新增的屬性被正確地儲存到資料函式庫中。
微服務與單體應用的對比
在上述修改中,我們只需要測試和佈署相關的服務即可。這與單體應用有著顯著不同。在單體應用中,即使是簡單的修改也需要重新構建整個應用並進行全面的迴歸測試,這樣非常耗時耗力。而微服務架構則允許我們只修改和佈署受影響的部分,從而大大縮短了開發週期。
解決傳統單體應用中的挑戰
我們來看看微服務架構如何幫助解決傳統單體應用中的一些常見挑戰:
地址錯誤
如果某個微服務出現錯誤,只需要修復該微服務即可。由於每個微服務通常都會進行負載平衡,因此可以逐步佈署修復版本而不影回應用的可用性。相比之下,單體應用中的錯誤可能需要重新佈署整個應用並進行全面測試。
此圖示展示了在微服務架構中處理錯誤的流程。
替換應用元件
例如,如果我們希望使用雲端服務來管理票據,只需要更改組態即可指向雲端服務的端點。這樣非常簡單且靈活。
此圖示展示了在微服務架構中替換應用元件的流程。
替換或新增新技術堆疊
如果需要使用不同技術堆疊(如PHP/NoSQL)來開發現有或新服務,開發者可以自由選擇技術而不受限於現有技術堆疊。
單獨擴充套件
微服務架構的一大優勢是可以選擇性地擴充套件。例如,如果票據層預計會有更多流量,可以輕鬆地增加票據服務的虛擬機器或容器數量而不影響其他服務或單體部分。這樣可以節省時間、資源和不必要的成本。
此圖示展示了在微服務架構中選擇性擴充套件的流程。
處理故障
如果某個微服務出現問題或故障,只會影響該微服務本身而不會波及整個系統。例如,在電子商務網站上,如果產品評價部分當機了,通常只會影響評價功能而不會影響購物車和結帳功能。而在單體應用中,這種情況可能會導致整個網站無法存取。
可擴充套件性挑戰
儘管微服務架構有許多優勢,但也面臨一些挑戰。例如,管理大量的微服務(如千篇以上)可能會變得非常複雜。因此,容器化技術(如Docker)成為了一種常見的解決方案。
下一步:容器化微服務
在下一章節中,我們將探討如何使用Docker容器化技術來佈署和擴充套件我們的微服務。透過容器化,我們可以更輕鬆地管理和擴充套件我們的應用。
玄貓認為:從單體架構遷移到微服務架構需要謹慎規劃和設計。透過逐步引入微服務並解決傳統單體應用中的挑戰,我們可以實作更高效、靈活和可擴充套件的系統設計。
將技術支援應用程式容器化
依賴列表
將技術支援應用程式容器化的過程中,首先需確認並列出所需的依賴軟體。以下是執行產品目錄微服務所需的軟體清單:
- Tomcat:用於執行產品目錄應用程式碼。
- Java:作為 Tomcat 的依賴,確保其正常運作。
- MySQL Connector:讓 Tomcat 能夠連線到 MySQL 資料函式庫。
- Apache Maven:必須安裝在構建微服務的系統上。如果需要參考安裝步驟,可以參考 Apache Maven 安裝。
構建二進位制檔案與 WAR 檔案
接下來,我們需要構建 WAR 檔案(二進位制檔案)。請按照以下步驟進行:
克隆程式碼:從 GitHub 儲存函式庫克隆技術支援微服務的程式碼。儲存函式庫位址:https://github.com/kocherMSD/Helpdesk_Microservices.git。
使用 Apache Maven 構建 WAR 檔案:由於我們正在構建第一個微服務,應該利用最新的工具。這裡我們選擇使用 Apache Maven 來構建 WAR 檔案,而非之前使用的 Apache Ant。Maven 是一個更先進的構建自動化工具,能夠自動下載專案所需的函式庫依賴。
檢查 POM 檔案:確保 Apache POM 檔案位於克隆程式碼的根目錄。POM 檔案包含專案的依賴、Java Runtime 版本、Maven 中央倉函式庫資訊以及所需的 JAR 檔案列表。
構建 WAR 檔案:在命令列中,於專案根目錄執行
mvn install命令,或者在 Eclipse 編輯器中右鍵點選 POM 檔案選擇mvn install。成功構建後,根目錄中應該會建立一個名為Target的資料夾,其中包含 WAR 檔案。
建立 Docker Image
接下來,我們來看看如何為產品目錄服務建立 Docker Image。對於其他微服務(例如票務微服務),建立 Image 的方法相同,僅需包含選定微服務的相應二進位制檔案及環境依賴。
Dockerfile 構建
如之前章節所學,建立 Docker Image 的正確方式是透過 Dockerfile,其中包含之前提到的所有依賴。
以下是逐步構建 Dockerfile 的過程:
# 根據 Ubuntu 17.04
FROM ubuntu:17.04
# 環境變數設定 Tomcat 7;根據需要更改 Tomcat 次要版本。
# 若要更改主要版本(例如 Tomcat 8),請確保同時更改 TOMCAT_LOCATION 變數。
ENV TOMCAT_VERSION=7.0.81
ENV TOMCAT_FILENAME=apache-tomcat-$TOMCAT_VERSION.tar.gz
ENV TOMCAT_DIRECTORY=apache-tomcat-$TOMCAT_VERSION
ENV TOMCAT_LOCATION=http://www-eu.apache.org/dist/tomcat/tomcat-7/v$TOMCAT_VERSION/bin/$TOMCAT_FILENAME
內容解密:
此段落作用與邏輯說明:
1. FROM ubuntu:17.04:指定基礎映像為 Ubuntu 17.04。
2. ENV 命令:設定環境變數供 Dockerfile 中後續步驟使用。
- TOMCAT_VERSION:定義要安裝的 Tomcat 需要版本。
- TOMCAT_FILENAME:定義要下載的 Tomcat 檔案名稱。
- TOMCAT_DIRECTORY:定義解壓後 Tomcat 的資料夾名稱。
- TOMCAT_LOCATION:定義 Tomcat 下載地址。
# 下載 Tomcat;安裝所需工具如 wget 和 JDK1.8。
# 清理 apt cache,因為 "apt-get update" 每次執行都會更新快取。
RUN apt-get update && \
apt-get install -y wget && \
apt-get install -y default-jdk && \
rm -fr /var/lib/apt/lists/* && \
wget $TOMCAT_LOCATION
內容解密:
此段落作用與邏輯說明:
1. apt-get update:更新軟體包列表以取得最新可用版本資訊。
2. apt-get install -y wget:安裝 wget 工具,用於從網路下載檔案。
3. apt-get install -y default-jdk:安裝 JDK,作為 Tomcat 的依賴。
4. rm -fr /var/lib/apt/lists/*:清理已更新的快取資料夾以減少映像大小。
5. wget $TOMCAT_LOCATION:使用 wget 下載指定版本的 Tomcat 檔案。
RUN 命令將這些操作封裝在一條命令中執行,以減少映像層數量並保持映像精簡。
# 在 /opt 目錄下安裝 Tomcat,並重新命名資料夾為 "tomcat"
RUN tar -xf $TOMCAT_FILENAME -C /opt && \
mv /opt/$TOMCAT_DIRECTORY /opt/tomcat
內容解密:
此段落作用與邏輯說明:
1. tar -xf $TOMCAT_FILENAME -C /opt:解壓縮下載的 Tomcat 檔案到 /opt 資料夾。
2. mv /opt/$TOMCAT_DIRECTORY /opt/tomcat:重新命名解壓後的資料夾為 tomcat。
這樣做是為了簡化目錄結構並使後續組態更加直觀。
# 將產品目錄微服務佈署到 Tomcat
ADD catalog-svc.war /opt/tomcat/webapps/
# 暴露埠到主機系統
EXPOSE 8080
內容解密:
此段落作用與邏輯說明:
1. ADD catalog-svc.war /opt/tomcat/webapps/:將預先構建好的 WAR 檔案新增到 Tomcat 的 webapps 資料夾中。這樣 Tomcat 能夠自動佈署並執行該微服務。
2. EXPOSE 8080:暴露埠號以允許外部存取應用程式。預設情況下,Tomcat 在 8080 接受請求。
這些步驟確保了產品目錄微服務能夠成功容器化並佈署在 Docker 中。
## Docker 應用於微服務佈署:從構建到執行
在現代軟體開發中,微服務架構已經成為主流。微服務的核心理念是將一個大型應用程式拆分成多個小型、獨立的服務,每個服務都可以獨立佈署和擴充套件。Docker 作為一個強大的容器化工具,能夠幫助我們將這些微服務進行封裝和管理。
### 使用 Docker 封裝 Tomcat 服務
首先,我們來看一個簡單的例子,展示如何使用 Docker 來封裝並執行一個 Tomcat 服務。這個例子中,我們將一個名為 `catalog-svc.war` 的應用程式佈署到 Tomcat 容器中。
#### Dockerfile 詳細解析
以下是完整的 Dockerfile:
```Dockerfile
# 根據 Ubuntu 17.04
FROM ubuntu:17.04
# 環境變數設定
ENV TOMCAT_VERSION=7.0.81
ENV TOMCAT_FILENAME=apache-tomcat-$TOMCAT_VERSION.tar.gz
ENV TOMCAT_DIRECTORY=apache-tomcat-$TOMCAT_VERSION
ENV TOMCAT_LOCATION=http://www-eu.apache.org/dist/tomcat/tomcat-7/v$TOMCAT_VERSION/bin/$TOMCAT_FILENAME
# 安裝必要的工具和 JDK
RUN apt-get update && \
apt-get install -y wget && \
apt-get install -y default-jdk && \
rm -fr /var/lib/apt/lists/* && \
wget $TOMCAT_LOCATION
# 安裝 Tomcat 並重新命名目錄
RUN tar -xf $TOMCAT_FILENAME -C /opt && \
mv /opt/$TOMCAT_DIRECTORY /opt/tomcat
# 將 WAR 檔案佈署到 Tomcat
ADD catalog-svc.war /opt/tomcat/webapps/
# 暴露 Tomcat 的埠
EXPOSE 8080
# 在前台執行 Tomcat
CMD ["/opt/tomcat/bin/catalina.sh", "run"]
內容解密:
- 基礎映像:使用
ubuntu:17.04作為基礎映像,這樣可以確保環境的一致性。 - 環境變數設定:設定 Tomcat 的版本和下載地址,這樣可以方便地更換不同版本的 Tomcat。
- 安裝必要工具:使用
apt-get安裝wget和default-jdk,這些工具是後續安裝 Tomcat 和執行 Java 應用所必需的。 - 下載並安裝 Tomcat:使用
wget下載 Tomcat 的壓縮檔,並解壓縮到/opt目錄下,然後重新命名目錄為tomcat。 - 佈署 WAR 檔案:將
catalog-svc.war檔案新增到 Tomcat 的webapps目錄中,這樣當容器啟動時,Tomcat 會自動佈署這個應用。 - 暴露埠:使用
EXPOSE指令暴露 Tomcat 的預設埠8080,這樣外部可以透過這個埠存取應用。 - 執行命令:使用
CMD指令設定預設命令為執行 Tomcat,這樣當容器啟動時,Tomcat 會自動啟動。
架構圖示:
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle
title 微服務遷移實戰:從單體架構到Docker容器化佈署
package "Docker 架構" {
actor "開發者" as dev
package "Docker Engine" {
component [Docker Daemon] as daemon
component [Docker CLI] as cli
component [REST API] as api
}
package "容器運行時" {
component [containerd] as containerd
component [runc] as runc
}
package "儲存" {
database [Images] as images
database [Volumes] as volumes
database [Networks] as networks
}
cloud "Registry" as registry
}
dev --> cli : 命令操作
cli --> api : API 呼叫
api --> daemon : 處理請求
daemon --> containerd : 容器管理
containerd --> runc : 執行容器
daemon --> images : 映像檔管理
daemon --> registry : 拉取/推送
daemon --> volumes : 資料持久化
daemon --> networks : 網路配置
@enduml此圖示展示了 Dockerfile 的步驟及其邏輯關係。
建立 Docker 畫素
有了 Dockerfile 之後,我們可以使用以下命令來建立 Docker 畫素:
docker build -t catalog-svc:1.0 .
內容解密:
- docker build:這是建立 Docker 畫素的命令。
- -t catalog-svc:1.0:指定建立的畫素名稱和標籤。在此例中,畫素名稱是
catalog-svc,標籤是1.0。 - .:表示當前目錄中的 Dockerfile 和相關檔案將被用來建立畫素。
在 AWS 上設定 DC/OS 叢集
我們可以利用 DC/OS(Datacenter Operating System)快速設定 Mesos 和 Marathon 環境。DC/OS 是根據 Apache Mesos 建立的開源分散式作業系統軟體,提供了簡單易用的方式來設定 Mesos、Marathon 和 Marathon-lb。
在 AWS 上建立 DC/OS 叢集
建立金鑰對:在 AWS 控制檯中,進入「網路與安全」->「金鑰對」,建立一個新的金鑰對。這個金鑰對將會在之後的叢集建立過程中使用。
啟動 EC2 啟例:根據 DC/OS 的官方檔案,使用 AWS 控制檯或 CLI 啟動 EC2 啟例。確保啟例組態符合 DC/OS 的要求。
安裝 DC/OS CLI:按照 DC/OS 的官方檔案安裝 DC/OS CLI 工具,這個工具可以幫助我們管理和佈署應用程式。
組態叢集:完成以上步驟後,就可以開始組態叢集並佈署應用程式了。DC/OS 提供了豐富的檔案和範例,可以幫助我們快速上手。
問題與挑戰
在實際操作中,可能會遇到一些問題和挑戰:
- 網路組態:確保所有節點之間能夠正常通訊。
- 安全性:確保所有敏感資訊都受到保護。
- 效能調優:根據實際需求調優叢集效能。