共用方式為


容器化的微服務

注意

本電子書於 2017 年春季出版,此後尚未更新。 這本書中有很多仍然有價值的,但一些材料已經過時。

開發用戶端伺服器應用程式已導致著重於建置階層式應用程式,以在每個層級使用特定技術。 這類應用程式通常稱為 整合型 應用程式,而且會封裝到預先調整為尖峰負載的硬體上。 此開發方法的主要缺點是每個層級中的元件之間緊密結合,因此無法輕易調整個別元件;另外測試的成本也是缺點。 簡單的更新可能會對層的其餘部分造成無法預期的影響,因此對應用程式元件的變更需要重新測試並重新部署整個層。

特別是在雲端時代,特別令人擔心的是,無法輕易調整個別元件。 整合型應用程式包含網域特定功能,通常除以功能層,例如前端、商業規則和數據記憶體。 整合型應用程式是藉由將整個應用程式複製到多部計算機來調整,如圖 8-1 所示。

Monolithic application scaling approach

圖 8-1:整合型應用程式調整方法

微服務

微服務提供不同的應用程式開發與部署方法,這是一種適合現代化雲端應用程式靈活度、規模與可靠性需求的方法。 微服務應用程式會分解成獨立元件,共同運作以提供應用程式的整體功能。 微服務一詞強調,應用程式應該由小到足以反映獨立考慮的服務所組成,讓每個微服務實作單一函式。 此外,每個微服務都有妥善定義的合約,讓其他微服務可以與其通訊及共享數據。 微服務的一般範例包括購物車、庫存處理、購買子系統,以及付款處理。

微服務可以獨立相應放大,與一起調整的巨型整合型應用程式相比。 這表示需要更多處理能力或網路頻寬來支援需求的特定功能區域,可以進行調整,而不是不必要地相應放大應用程式的其他區域。 圖 8-2 說明此方法,其中微服務會獨立部署和調整,以跨機器建立服務的實例。

Diagram shows two apps with tiles representing different functional areas and six rectangles hosting various functional areas from both apps.

圖 8-2:微服務應用程式調整方法

微服務擴增幾乎可以立即完成,讓應用程式能夠適應變更的負載。 例如,應用程式 Web 面向功能中的單一微服務可能是應用程式中唯一需要相應放大以處理其他連入流量的微服務。

應用程式可擴縮性的傳統模型是具有負載平衡的無狀態層,且具有共用外部資料存放區以儲存持續性資料。 具狀態微服務會管理自己的永續性資料,通常會將其儲存於放置自身的伺服器上,以避免網路存取的額外負荷,以及跨服務作業的複雜度。 這可讓資料的處理速度最快,且可消除快取系統的需求。 此外,可調整的具狀態微服務通常會在其實例之間分割數據,以管理數據大小並傳輸輸送量,而單一伺服器可以支持的數據大小和傳輸輸送量。

微服務也支援獨立更新。 微服務之間的這種鬆散結合可提供快速且可靠的應用程式演進。 其獨立分散式本質支援滾動更新,其中只有單一微服務的實例子集在任何指定時間都會更新。 因此,若偵測到問題,可以在所有執行個體更新錯誤碼或組態之前復原有 Bug 的更新。 同樣地,微服務通常會使用結構描述版本設定,讓用戶端在套用更新時,不論要與哪個微服務執行個體進行通訊,都會看到一致的版本。

因此,微服務應用程式對於整合型應用程式有許多優點:

  • 每個微服務相對較小,因此管理及發展都很容易。
  • 每個微服務都可獨立部署及更新,而不影響其他服務。
  • 每個微服務都可以獨立擴增。 例如,目錄服務或購物籃服務可能需要擴增得比訂購服務多。 因此,擴增時,產生的基礎結構將更有效率地取用資源。
  • 每個微服務都會隔離任何問題。 例如,若某個服務中有問題,問題只會影響該服務。 其他服務可以繼續處理要求。
  • 每個微服務都可以使用最新技術。 因為微服務是自主且並存執行,所以可以使用最新的技術與架構,而不是強制使用整合型應用程式可能使用的舊版架構。

不過,微服務型解決方案也有潛在的缺點:

  • 選擇如何將應用程式分割成微服務可能很困難,因為每個微服務都必須完全自主、端對端,包括對其資料來源的責任。
  • 開發人員必須實作服務間通訊,這會增加應用程式的複雜度與延遲。
  • 多個微服務之間不可部分完成的交易通常不可行。 因此,商務需求必須在微服務之間採用最終一致性。
  • 在生產環境中,部署及管理許多獨立服務遭入侵的系統具有作業複雜度。
  • 直接用戶端對微服務通訊可能會使重構微服務的合約變得困難。 例如,經過一段時間後,系統分割成服務的方式可能需要變更。 單一服務可能會分割成兩個或多個服務,而兩個服務可能會合併。 當用戶端直接與微服務通訊時,此重構作業可能會中斷與用戶端應用程式的相容性。

貨櫃化

容器化是軟體開發的方法,其中會將應用程式及其版本設定相依性集合,以及其抽象化為部署資訊清單檔案的環境組態封裝為容器映像、測試為單位,並部署至主機作業系統。

容器是隔離、資源控制的可攜式作業環境,應用程式可以在不觸碰其他容器或主機資源的情況下執行。 因此,容器的外觀與行為會如同新安裝的實體電腦或虛擬機器。

容器和虛擬機之間有許多相似之處,如圖 8-3 所示。

Diagram shows a comparison between Virtual Machines and Containers, where virtual machines have three apps each siloed on a guest O S, with a hypervisor and a host O S, and the containers have three apps hosted in a container engine on a single OS.

圖 8-3:虛擬機和容器的比較

容器可像實體或虛擬機器一樣執行作業系統、具有檔案系統,且可透過網路來存取。 然而,容器所使用的技術與概念還是與虛擬機器非常不同。 虛擬機器包含應用程式、必要的相依性,以及完整的客體作業系統。 容器包含應用程式及其相依性,但與其他容器共用作業系統,在主機作業系統上以獨立的處理序執行 (除了每個容器在特殊虛擬機器中執行的 Hyper-V 容器之外)。 因此,容器會共用資源,且通常需要比虛擬機器更少的資源。

容器導向開發與部署方法的優點是,其會消除大部分因環境設定不一致而發生的問題,以及其隨附的問題。 此外,容器會視需要將新的容器執行個體化,以允許快速的應用程式擴大功能。

建立及使用容器時的重要概念為:

  • 容器主機:設定為裝載容器的實體或虛擬機。 容器主機將會執行一或多個容器。
  • 容器映射:映像是由堆疊在彼此之上的分層文件系統聯集所組成,而且是容器的基礎。 映像沒有狀態,且在部署至不同環境時一律不會變更。
  • 容器:容器是映像的運行時間實例。
  • 容器OS映像:容器會從映像部署。 在可能構成容器的眾多映像層中,容器作業系統映像是第一層。 容器作業系統不可變,而且無法修改。
  • 容器存放庫:每次建立容器映射時,映像及其相依性都會儲存在本機存放庫中。 這些映像可在容器主機上重複使用多次。 容器映像也可以儲存於公用或私人登錄中 (例如 Docker Hub),以便在許多不同的容器主機之間使用。

企業在實作微服務型應用程式時越來越採用容器,而 Docker 已成為大部分軟體平臺和雲端廠商採用的標準容器實作。

eShopOnContainers 參考應用程式會使用 Docker 來裝載四個容器化的後端微服務,如圖 8-4 所示。

eShopOnContainers reference application back-end microservices

圖 8-4:eShopOnContainers 參考應用程式後端微服務

參考應用程式中後端服務的架構會以共同作業微服務與容器的形式分解成多個自主子系統。 每個微服務都提供單一功能區域:身分識別服務、目錄服務、訂購服務,以及購物籃服務。

每個微服務都有自己的資料庫,因此可與其他微服務完全分離。 必要時,會使用應用程式層級事件來達成不同微服務資料庫之間的一致性。 如需詳細資訊,請參閱 微服務之間的通訊。

如需參考應用程式的詳細資訊,請參閱 .NET 微服務:容器化 .NET 應用程式的架構

用戶端與微服務之間的通訊

eShopOnContainers 行動應用程式會使用 直接用戶端對微服務 通訊來與容器化後端微服務通訊,如圖 8-5 所示。

Diagram shows an app hosted on a mobile device connected to three Backend Microservices, each with its own Web A P I Container.

圖 8-5:直接用戶端對微服務通訊

透過直接用戶端對微服務通訊,行動應用程式會透過其公用端點直接向每個微服務提出要求,每個微服務有不同的 TCP 連接埠。 在生產環境中,端點通常會對應至微服務的負載平衡器,這會在可用的微服務執行個體之間散發要求。

提示

請考慮使用 API 閘道通訊。 建置大型和複雜的微服務型應用程式時,直接用戶端對微服務通訊可能會有缺點,但對於小型應用程序來說,這還不夠。 使用數十個微服務設計大型微服務型應用程式時,請考慮使用 API 閘道通訊。 如需詳細資訊,請參閱 .NET 微服務:容器化 .NET 應用程式的架構

微服務之間的通訊

微服務型應用程式是分散式系統,可能會在多部計算機上執行。 每個服務執行個體通常就是一個處理序。 因此,服務必須使用處理序間的通訊協定 (例如 HTTP、TCP、進階訊息佇列通訊協定 (AMQP) 或二進位通訊協定,根據每個服務的本質) 來互動。

微服務對微服務通訊的兩個常見方法是查詢數據時的 HTTP 型 REST 通訊,以及在跨多個微服務通訊更新時進行輕量型異步傳訊。

在跨多個微服務傳播變更時,以異步傳訊為基礎的事件導向通訊非常重要。 透過此方法,微服務會在發生值得注意的情況時發行事件;例如,當其更新商務實體時。 其他微服務會訂閱這些事件。 然後,當微服務收到事件時,它會更新自己的商務實體,這反過來可能會導致發佈更多事件。 此發行-訂閱功能通常是透過事件匯流排來達成。

事件總線允許微服務之間的發佈-訂閱通訊,而不需要元件明確感知彼此,如圖 8-6 所示。

Publish-subscribe with an event bus

圖 8-6: 使用事件總線發佈訂閱

從應用程式的觀點來看,事件匯流排只是一個透過介面公開的發行-訂閱通道。 然而,實作事件匯流排的方式可能會有所不同。 例如,事件匯流排實作可以使用 RabbitMQ、Azure 服務匯流排或其他服務匯流排,例如 NServiceBus 與 MassTransit。 圖 8-7 顯示如何在 eShopOnContainers 參考應用程式中使用事件總線。

Asynchronous event-driven communication in the reference application

圖 8-7: 參考應用程式中的異步事件驅動通訊

使用 RabbitMQ 實作的 eShopOnContainers 事件匯流排提供一對多非同步發行-訂閱功能。 這表示在發行事件之後,可以有多個訂閱者接聽相同的事件。 圖 8-9 說明此關聯性。

One-to-many communication

圖 8-9:一對多通訊

此一對多通訊方法會使用事件實作跨越多個服務的商務交易,以確保服務之間的最終一致性。 最終一致的交易是由一系列的分散式步驟所組成。 因此,當使用者設定檔微服務收到 UpdateUser 命令時,它會更新其資料庫中的使用者詳細資料,並將 UserUpdated 事件發行至事件匯流排。 購物籃微服務和訂購微服務都已訂閱接收此事件,並回應更新其各自資料庫中的購買者資訊。

注意

使用 RabbitMQ 實作的 eShopOnContainers 事件匯流排僅供概念證明使用。 針對生產環境系統,應該考慮替代事件匯流排實作。

如需事件總線實作的相關信息,請參閱 .NET 微服務:容器化 .NET 應用程式的架構。

摘要

微服務提供應用程式開發與部署的方法,這是一種適合現代化雲端應用程式靈活度、規模與可靠性需求的方法。 微服務的主要優點之一是可以獨立相應放大,這表示可以調整特定功能區域,需要更多處理能力或網路頻寬來支援需求,而不需要不必要的調整應用程式區域,而不需要增加需求。

容器是隔離、資源控制的可攜式作業環境,應用程式可以在不觸碰其他容器或主機資源的情況下執行。 企業在實作微服務型應用程式時越來越採用容器,而 Docker 已成為大部分軟體平臺和雲端廠商採用的標準容器實作。