這是學習路徑的第二堂教學課程,說明如何將單體式應用程式模組化及容器化。
這個學習路徑包含下列教學課程:
- 總覽
- 瞭解單體式架構
- 將單體應用程式模組化 (本教學課程)
- 準備將模組化應用程式容器化
- 將模組化應用程式容器化
- 將應用程式部署至 GKE 叢集
在先前的教學課程「瞭解單體式架構」中,您已瞭解名為 Cymbal Books 的單體式應用程式。您在本地電腦上執行單體式應用程式,並瞭解單體式應用程式的不同部分會透過端點彼此通訊。
在本教學課程中,您將瞭解如何將單體式架構劃分為多個模組,為容器化做好準備。程式碼已為您更新,因此您不需要自行執行模組化步驟。您的工作是按照教學課程操作,並探索存放區中的模組化應用程式版本,瞭解該版本與原始單體式應用程式的差異。
費用
完成本教學課程不會產生任何費用。不過,按照本系列最後一個教學課程中的步驟操作,會導致您的Google Cloud 帳戶產生費用。啟用 GKE 並將 Cymbal Books 應用程式部署至 GKE 叢集後,就會開始產生費用。這些費用包括 GKE 的叢集費用 (如定價頁面所述),以及執行 Compute Engine VM 的費用。
為避免產生不必要的費用,請務必在完成本教學課程後停用 GKE 或刪除專案。
事前準備
開始本教學課程前,請務必先完成第一個教學課程「瞭解單體式架構」。在本教學課程中,您會在自己的電腦上執行 Cymbal Books 的模組化版本。如要這麼做,您必須先設定環境。如果您已完成第一個教學課程,應該已複製 GitHub 存放區。Cymbal Books 應用程式的三個版本都位於該存放區的下列資料夾中:
monolith/
modular/
containerized/
請先確認這些資料夾位於電腦上,再繼續操作。此外,請確認虛擬環境 book-review-env
已啟用。如需啟動虛擬環境的提醒,請參閱第一個教學課程中的「建立及啟動虛擬環境」。啟用環境可確保應用程式的模組化版本具備執行所需的一切。
什麼是模組化?
在本教學課程中,您將瞭解如何將單體式應用程式模組化,以便準備容器化。模組化是將單體轉換為模組化應用程式的過程。如先前教學課程所述,單體的顯著特徵是其元件無法獨立執行或擴充。模組化應用程式則不同,其功能會劃分為可獨立執行及擴充的模組。
雖然模組化和容器化通常會一併完成,但在這一系列的教學課程中,我們會將這兩者視為個別步驟,協助您清楚瞭解每個概念。本教學課程說明如何將單體式應用程式模組化,後續教學課程則會說明如何將模組化應用程式容器化。
逐步模組化
在實際工作環境中,您通常一次模組化一個元件。您將元件模組化、將模組與單體式架構整合,並確保一切運作正常,再處理下一個元件。這種混合狀態稱為「微單體」,部分元件會模組化,其他元件則仍屬於單體。不過在本教學課程中,所有應用程式元件都會同時模組化,提供應用程式模組化的完整範例。
如何將單體應用程式模組化
在本節中,您將瞭解如何將 Cymbal Books 單體式架構拆分成獨立模組。我們提供步驟說明,協助您瞭解模組化程序,並將其套用至自己的應用程式。不過,在本教學課程中您不需要執行這些步驟,因為複製的存放區已包含應用程式的模組化版本:
找出應用程式的獨特功能
將 Cymbal Books 單體式架構模組化的第一步,是找出主要功能。在 Cymbal Books 範例應用程式中,單體式應用程式具有下列四個不同的功能:
- 提供首頁
- 提供書籍詳細資料
- 提供書評
- 提供書籍封面圖片
建立模組
如前一個教學課程所示,單體式架構是實作四個函式的單一 Flask 應用程式,這四個函式在前一節中已識別為路徑處理常式。如要將應用程式模組化,請將每個路徑處理常式放入各自的 Flask 應用程式。您會有四個 Flask 應用程式,每個應用程式內都有單一路徑處理常式,而不是一個 Flask 應用程式和四個路徑處理常式。
下圖說明如何將單一 Flask 應用程式轉換為四個獨立的 Flask 應用程式:
在模組化應用程式中,每個 Flask 應用程式都會獨立執行,並監聽不同的通訊埠 (8080、8081、8082、8083),如圖所示。這是必要設定,因為在本教學課程稍後測試模組化應用程式時,您會在同一部機器上執行所有模組。每個應用程式都需要不同的通訊埠號碼,以免發生衝突。
首頁模組有兩項職責:提供首頁,以及與其他模組通訊,以收集需要在網頁中顯示的資料。其他模組則分別專注於單一功能:提供評論、詳細資料或圖片。這些模組不會彼此通訊,只會回應首頁模組的要求。
雖然首頁模組具有額外的協調角色,但應用程式仍是真正的模組化,因為您可以更新任何模組,而不會影響其他模組。大型 Flask 應用程式已拆解成四個部分,每個部分負責處理應用程式功能的特定部分。
啟用模組間的通訊
建立模組後,下一步是確保模組可以彼此通訊。在 Cymbal Books 應用程式中,這項通訊邏輯已為您導入。在您下載的程式碼的 modular/
資料夾中,可以看到應用程式的各項主要功能 (提供首頁、書籍詳細資料、評論和圖片) 都是以獨立的 Flask 應用程式實作。每個應用程式都會定義自己的 HTTP 端點,而模組會透過傳送 HTTP 要求至這些端點來進行通訊。
Cymbal Books 單體式架構的模組化作業相當簡單,單體式架構具有明確定義的元件,這些元件會實作為路徑處理常式,且每個路徑處理常式都有明確定義的端點。當這些路徑處理常式放置在不同的 Flask 應用程式中時,仍可透過端點進行通訊。將路徑處理常式放入個別 Flask 應用程式的簡單動作,既可建立模組,也能讓模組彼此通訊。
模組間通訊的常見做法是實作 REST API,讓模組可以互相傳送 HTTP 要求。Cymbal Books 就是這樣運作:每個模組都會使用 Flask 的內建工具定義 REST 端點。另一個熱門方法是 gRPC,可讓模組直接呼叫彼此的函式。
為何 Cymbal Books 的溝通方式簡單明瞭
模組化應用程式中的每個模組都是獨立的 Flask 應用程式,會在網路伺服器中執行。舉例來說,首頁模組會提供首頁,書籍詳細資料模組則會提供書籍詳細資料。由於網頁伺服器專門處理 HTTP 要求和回應,因此模組之間的通訊相當簡單。每個模組都會公開端點,供其他模組用來要求資料。
只允許每個模組存取所需的資料
如要正確模組化單體應用程式,請務必確保每個模組只能存取所需的資料。這項原則稱為資料隔離,是建立真正模組化架構的關鍵要素。
在模組化期間,人們常犯的錯誤是允許多個模組存取相同資料,例如單一資料庫。這類實作方式會造成下列問題:
- 緊密耦合:如果共用資料的結構發生變化 (例如資料庫表格重新命名或新增資料欄),所有依附於該資料的模組都必須更新。妥善模組化可避免這個問題。
- 容錯問題:如果多個模組使用相同的資料來源,一個模組發生執行階段錯誤 (例如無效查詢或流量過大),可能會中斷其他模組。系統某個部分發生故障時,可能會連帶導致其他部分也故障。
- 效能瓶頸:單一共用資料來源可能會成為瓶頸,也就是說,當多個模組嘗試與其互動時,可能會拖慢整個應用程式的速度。
為避免這些問題,每個模組都應有自己的資料來源。
如果 Cymbal Books 使用資料庫儲存資料,您必須複製或分割資料庫,才能強制執行資料隔離,並確保每個模組只存取所需的資料。複製作業會為每個模組維護個別的資料庫副本,而分割作業則會限制對特定資料表或資料列的存取權。這兩種方法都能防止模組互相干擾資料。
下圖比較了書籍應用程式的單體式架構與模組化架構:
單體式應用程式的實作方式不符合資料隔離原則,因為單體式應用程式的函式會存取單一 data/
目錄。
相較之下,模組化應用程式會將資料分割到不同目錄,並確保每個模組只與指定資料互動,藉此達到某種程度的資料隔離:
- 書籍詳細資料模組只會從
details_data/
目錄取得資料。 - 書籍評論模組只會從
reviews_data/
目錄取得資料。 - 圖片模組只會從
images/
目錄取得資料。
在後續教學課程中,您會瞭解如何將應用程式容器化,進一步強化資料隔離。
您剛才看到的內容
在軟體開發產業中,您經常會遇到「微服務」和「分散式系統」這兩個詞彙。本節說明這些術語與 Cymbal Books 的模組化實作方式有何關聯。
微服務
微服務是執行特定工作的自主模組,這些模組會透過端點等介面與其他模組通訊。
Cymbal Books 模組化版本中的每個模組都符合這項定義,因此可以稱為微服務。在後續教學課程中,模組化應用程式會容器化,因此在容器內執行的程式碼也可稱為微服務,因為這與在模組內執行的程式碼相同。
分散式系統
分散式系統由獨立模組組成,這些模組透過網路通訊,以達成共同目標。這些模組可以在不同機器上執行,但會共同運作,形成單一系統。
模組化 Cymbal Books 應用程式也符合這項定義:其模組會獨立執行,並透過 HTTP 交換資料,但會共同運作,形成單一系統。在下一節中,為求簡單,您會在單一機器上執行所有模組,但這並非必要。每個模組同樣可以輕鬆在不同伺服器上執行,這就是 Cymbal Books 應用程式的模組化版本可以歸類為分散式系統的原因。
測試模組化實作
您已瞭解如何將 Cymbal Books 單體式應用程式轉換為模組化應用程式,且模組都是 Flask 應用程式。現在可以測試應用程式,並確認每個模組都能獨立執行。
在本教學課程中,您會在同一部機器上執行模組。不過,您也可以在個別伺服器上執行每個模組,因為每個模組都是自主的,可以透過端點與其他模組通訊。
設定環境
請按照下列步驟準備測試:
在終端機中,前往複製存放區中的
modular
目錄:cd modular
確認虛擬環境
book-review-env
已啟用。如需啟動步驟的提醒,請參閱「建立及啟動虛擬環境」。
啟動 Flask 應用程式
/modular
資料夾包含一個 Bash 指令碼,可同時啟動所有 Flask 應用程式。應用程式的每個模組都會監聽專屬通訊埠,例如 8080 或 8081:
- 首頁 Flask 應用程式 (home.py):通訊埠 8080
- 書籍詳細資料 Flask 應用程式 (book_details.py):連接埠 8081
- 書籍評論 Flask 應用程式 (book_reviews.py):連接埠 8082
- 圖片 Flask 應用程式 (images.py):連接埠 8083
由於所有模組都在同一部機器上執行,因此每個模組都必須監聽不重複的連接埠號碼。如果每個模組位於不同的伺服器上,每個模組都可以監聽相同的連接埠號碼,不會造成連接埠衝突。
使用下列指令執行 bash 指令碼:
bash ./start_services.sh
這個指令碼會為每個 Flask 應用程式 (例如 home.py.log
、book_details.py.log
) 建立個別的記錄檔,協助您找出任何啟動問題。指令碼成功完成後,您會看到這則訊息:
All services have been started. Access the app at http://localhost:8080/
測試每個 Flask 應用程式
在瀏覽器中前往下列網址,測試模組:
- 首頁:
http://localhost:8080/
會顯示模組化 Cymbal Books 應用程式的首頁。這個頁面會向其他模組提出要求,以擷取書籍詳細資料、評論和圖片。 - 書籍詳細資料:
http://localhost:8081/book/1
傳回 ID 為 1 的書籍詳細資料。這項回覆是 JSON 資料,應用程式會將其格式化,並以更易於閱讀的方式顯示。 - 書評:
http://localhost:8082/book/1/reviews
擷取並傳回 ID 為 1 的書籍評論。評論會以 JSON 格式匯出。首頁模組會要求這項資料,並將其整合至書籍詳細資料頁面。 - 圖片:
http://localhost:8083/images/fungi_frontier.jpg
會提供「真菌邊境」的書封圖片。如果網址正確,圖片應會直接載入瀏覽器。
停止 Flask 應用程式
測試完成後,請使用下列指令停止所有 Flask 應用程式:
kill $(cat home.py.pid book_details.py.pid book_reviews.py.pid images.py.pid)
摘要
本教學課程說明如何將 Cymbal Books 單體式架構模組化。這個程序包含下列步驟:
- 找出應用程式的獨特元件
- 建立模組
- 確保每個模組只能存取所需的資料
然後在本機電腦上測試模組化實作。
後續步驟
在下一個教學課程「準備將模組化應用程式容器化」中,您將瞭解如何更新端點,改用 Kubernetes 服務名稱而非 localhost
,為模組化應用程式容器化做好準備。