微服務架構的多種部署模式

微服務架構的多種部署模式

聲明:本文主要內容來自《微服務架構設計模式》

部署包含兩個互相關聯的概念:流程和架構。部署流程包括一些由開發人員和運維人員執行的過程,以便將軟件發佈到生產環境。部署架構定義了該軟件運行的環境結構。

以微服務架構開發的程序,經常涉及到多個服務組成,後端的網關模塊,用戶模塊,日誌模塊,業務模塊等,還有前端Node.js模塊。以筆者所在公司為例,每次部署服務時都要互相之間溝通協調好,方便服務之間的調用。一般在開發環境中多以jar形式部署,從本地直接打包發佈到服務器,方便快捷,適合與其他業務調試時及時解決修復問題。但這樣也存在一定的弊端,由於本地打包都是自己修改後的代碼,如果沒有及時將更改提交到git上,很容易遺漏其他協作開發的同事的代碼,可能自己的代碼調試完成,同事的卻出現問題。

微服務架構的多種部署模式

圖中抽象描述微服務架構中多種服務的組成和調用關係

當涉及測試和生產環境的部署時,需要注意的地方更多,打包上傳這種方式存在很大的漏洞,不夠流程化,而且服務器上可能運行各種語言和框架編寫的服務,每個服務都是一個小應用程序,這意味著你在生產環境中有數十或數百個應用程序。因此讓系統管理員手動配置服務器和服務已不再可行。如果要大規模部署微服務,則需要高度自動化的部署流程和基礎設施。

生產環境必須實現四個關鍵功能:

  • 服務管理接口: 使開發人員能夠創建、更新和配置服務。理想情況下,這個接口是一個可供命令行和圖形部署工具調用的REST API。
  • 運行時服務管理:確保始終運行著所需數量的服務實例。如果服務實例崩潰或由於某種原因無法處理請求,則生產環境必須重新啟動它。如果運行服務的主機發生崩潰,則必須在其他主機上重新啟動這些服務實例。
  • 監控:讓開發人員深入瞭解服務正在做什麼,包括日誌文件和各種應用指標。如果出現問題,必須提醒開發人員,也稱為可觀測性。
  • 請求路由:將用戶的請求路由到服務。

概述

故本文將闡述三個關鍵部署模式,並分析它們的好處和弊端。

  1. 編程語言特定的發佈包格式,例如Java JAR或WAR文件。我並不推薦這種做法,之所以介紹這個選項,是因為這個部署方法有各種顯著的缺點,會促使你思考和選擇其他更為合理和現代化的部署技術。
  2. 將服務部署為虛擬機,把服務打包為虛擬機鏡像,這個鏡像封裝了服務的技術棧,這樣可以簡化部署。
  3. 將服務部署為容器,這些容器比虛擬機更輕量級。

1 編程語言特定的發佈包格式

假設你要部署一個基於Spring Boot的Java應用程序。部署此服務的一種方法是使用特定於編程語言的軟件包部署服務。使用此模式時,生產環境中部署的內容以及服務運行時管理的內容都是特定於語言的發佈包中的服務。在Restaurant service的場景下,它是可執行的JAR文件或WAR文件。對於其他語言,例如Nodejs,服務是源代碼和模塊的目錄。對於某些語言,例如GoLang,服務是特定於操作系統某個路徑下的可執行文件。

模式:編程語言特定的發佈包格式,使用特定於編程語言的軟件發佈包將服務部署到生產環境。

要在計算機上部署Java應用程序,首先要安裝必要的運行時,在本例中為JDK。如果它是WAR文件,則還需要安裝Web容器,例如Apache Tomcat。配置完計算機後,將程序發佈包複製到計算機並啟動該服務。每個服務實例都作為JVM進程運行。理想情況下,你已經設置好部署流水線,它會自動將服務部署到生產環境。部署流水線構建可執行的JAR文件或WAR文件,然後它們調用生產環境的服務管理接口來部署新版本。


服務實例通常是單個進程,但有時可能是一組進程。例如,Java服務實例是運行JVM的進程。 Node js服務可能會生成多個工作進程,以便同時處理請求。某些語言支持在同一進程中部署多個服務實例。 有時,可以在計算機上部署單個服務實例,同時保留在同一臺計算機上部署多個服務實例的選項。例如,如圖12-4所示,可以在一臺計算機上運行多個JVM每個JVM都運行個服務實例。

微服務架構的多種部署模式

圖中在同一臺計算機上部署多個服務實例它們可能是相同服務的實例,也可能是不同服務的實例。操作系統的開銷在服務實例之間共享。每個服務實例都是一個單獨的進程,因此它們之間存在一些隔離。


微服務架構的多種部署模式

某些語言還允許在單個進程中運行多個服務實例。例如,如圖所示,可以在單個 Apache Tomcat上運行多個Java服務。 進程,在同一Web容器或應用程序服務器上部署多個服務實例。它們可能是相同服務的實例,也可能是不同服務的實例。操作系統和運行時的開銷在所有服務實例之間共享。但是因為服務實例處於同一個進程中,所以它們之間沒有隔離。

將服務作為特定於語言的發佈包進行部署的模式有好處也有弊端。我們先來看看好處。

使用編程語言特定的發佈包格式進行部署的好處

將服務作為特定於編程語言的發佈包進行部署有以下好處:

  • 快速部署。
  • 高效的資源利用,尤其是在同一臺機器上或同一進程中運行多個實例時。

我們來逐一分析。

快速部署

這種模式的一個主要好處是部署服務實例的速度相對較快:將服務複製到主機並啟動它。如果服務是用Java編寫的,則複製JAR或WAR文件。對於其他語言,例如js或Ruby,可以複製源代碼。在任何一種情況下,需要通過網絡複製的字節數相對較小。此外,啟動服務耗時很短。如果服務運行於自己獨佔的進程,則啟動它。否則,如果服務是在同一Web容器(例如Tomcat)進程中運行的多個實例之一,則可以將其動態部署到Web容器中,也可以重新啟動Web容器。由於沒有額外的開銷,因此啟動服務通常很快。

高效的資源利用

這種模式的另一個主要好處是它可以相對高效地使用資源。多個服務實例共享機器及其操作系統。如果多個服務實例在同一進程中運行,則效率更高。例如,多個Web應用程序可以共享相同的 Apache Tomcat服務器和JVM。

使用編程語言特定的發佈包格式進行部署的弊端

儘管極具吸引力,但把服務作為特定於編程語言的發佈包進行部署的模式有幾個顯著的

  • 缺乏對技術棧的封裝。
  • 無法約束服務實例消耗的資源。
  • 在同一臺計算機上運行多個服務實例時缺少隔離。
  • 很難自動判定放置服務實例的位置。

我們來逐一分析。

缺乏對技術棧的封裝

運維團隊必須瞭解部署每個服務的具體細節每個服務都需要特定版本的運行時。例如, Java Web應用程序需要特定版本的 Apache Tomcat和JDK運維團隊必須安裝每個所需軟件包的正確版本。 更糟糕的是,服務可以用各種語言和框架編寫。它們也可能用這些語言和框架的多個版本編寫。因此,開發團隊必須(以人工的方式)與運維團隊分享許多細節。這種溝通的複雜性增加了部署期間出錯的風險。例如,機器可能安裝錯誤的語言運行時版本。

無法約束服務實例消耗的資源

另一個缺點是你無法約束服務實例所消耗的資源。一個進程可能會消耗機器的所有CPU或內存,爭用其他服務實例和操作系統的資源。例如,出現某個錯誤,這種情況極有可能會發生。

在同一臺計算機上運行多個服務實例時缺少隔離

在同一臺計算機上運行多個實例時,問題更嚴重。缺乏隔離意味著行為不當的服務實例可能會影響其他服務實例。因此,應用程序存在不可靠的風險,尤其是在同一臺計算機上運行多個服務實例時。

很難自動判定放置服務實例的位置

在同一臺計算機上運行多個服務實例的另一個挑戰是確定服務實例的位置。每臺機器都有一組固定的資源、CPU、內存等,每個服務實例都需要一定的資源。以一種有效使用機器而不會使它們過載的方式將服務實例分配給機器非常重要。正如我稍後解釋的那樣,基於虛擬機的雲主機和容器編排框架會自動處理這個問題。在本地部署服務時,你可能需要手動確定放置位置。

正如你所看到的,服務作為特定於語言的發佈包進行部署的模式具有一些顯著的弊端。應該儘量避免使用這種方法,除非所獲效率的價值遠在其他所有考量之上。

2 將服務部署為虛擬機

模式:將服務部署為虛擬機,將作為虛擬機鏡像打包的服務部署到生產環境中。每個服務實例都是一個虛擬機。虛擬機鏡像由服務的部署流水線構建。部署流水線運行虛擬機鏡像構建器,這個構建器創建包含服務代碼和服務運行所需的任何軟件的虛擬機鏡像。例如,服務的安裝JDK和服務的可執行JAR的虛擬機構建器。虛擬機鏡像構建器使用 Linux的init系統(如 upstart)將虛擬機鏡像配置成在虛擬機引導時運行該應用程序。

部署流水線可以使用各種工具來構建虛擬機鏡像。一個早期創建EC2AMI的工具是由 netflix aminator ( https://github. com/netflix/a ) Netflix AWS開發的Aminatorhtp:github.cm/netflix/aminator),netflix使用它在aws上部署其視頻流服務 packer ( https://www.packer. io )是一個更現代的虛擬機鏡像構建器,與 Aminator不同,它支持各種虛擬化技術,包括EC2 Digital Ocean、 Virtual Box和 VMware要使用 Packer創建AMI,你需要編寫一個配置文件,用於指定基礎鏡像和一組安裝軟件並配置AMI的配置程序。

關於它的好處和弊端

將服務部署為虛擬機的好處

  • 虛擬機鏡像封裝了技術棧。
  • 隔離的服務實例。
  • 使用成熟的雲計算基礎設施。

我們來逐一分析。

虛擬機鏡像封裝了技術棧

此模式的一個重要好處是虛擬機鏡像包含服務及其所有依賴項。它消除了錯誤來源,確保正確安裝和設置服務運行所需的軟件。一旦服務被打包為虛擬機,它就會變成一個黑盒子,封裝服務的技術棧。虛擬機鏡像可以無須修改地部署在任何地方。用於部署服務的API成為虛擬機管理API。部署變得更加簡單和可靠。

隔離的服務實例

虛擬機的另一個好處是每個服務實例都以完全隔離的方式運行。畢竟,這是虛擬機技術的主要目標之一。每臺虛擬機都有固定數量的CPU和內存,不能從其他服務中竊取資源。

使用成熟的雲計算基礎設施

將微服務部署為虛擬機時,可以利用成熟且高度自動化的雲計算基礎設施。AWS等公共雲試圖以避免機器過載的方式在物理機上調度虛擬機。它們還提供有價值的功能,例如跨虛擬機的流量負載均衡和自動擴展。

將服務部署為虛擬機的弊端

  • 資源利用效率較低。
  • 部署速度相對較慢。
  • 系統管理的額外開銷。
資源利用效率較低。

每個服務實例擁有一整臺虛擬機的開銷,包括其操作系統。此外,典型的公共IaaS虛擬機提供有限的虛擬機配置組合,因此虛擬機可能未得到充分利用。這不太可能成為基於Java的服務的問題,因為它們一般都相對較重。但這種模式可能是部署輕量級 Nodejs和 GoLang服務的低效方式。

部署速度相對較慢

由於虛擬機的大小,構建虛擬機鏡像通常需要幾分鐘。有很多內容要通過網絡傳輸。此外,由於必須通過網絡傳輸完整的虛擬機鏡像文件,從鏡像實例化虛擬機是非常耗時的。在虛擬機內部運行的操作系統也需要一些時間來啟動,儘管慢速是一個相對的術語。這個過程可能需要幾分鐘,比傳統的部署過程要快得多。但它比你即將學習的更輕量級的部署模式要慢得多。

系統管理的額外開銷

你不得不擔負起給操作系統和運行時打補丁的責任。這對於部署軟件時的系統管理似乎是不可避免的,但在後面的12.5節中,我Serverless將描述部署,它消除了這種系統管理的方式。

現在讓我們看一下部署微服務更加輕量但仍每一個容器都是隔離進程的沙箱具有虛擬機諸多優點的替代方法。

3 將服務部署為容器

容器是一種更現代、更輕量級的部署機制,是一種操作系統級的虛擬化機制。容器通常包含一個或多個在沙箱中運行的進程,這個沙箱將它們與其他容器隔離。例如,運行Java服務的容器通常由JVM進程組成。 從在容器中運行的進程的角度來看,它就好像在自己的機器上運行一樣。它通常有自己的機器IP地址,可以消除端口衝突。例如,所有Java由所有容器共享進程都可以偵聽端口8080。每個容器也有自己的根文件系統。容器運行時使用操作系統機制將容器彼此隔離。

微服務架構的多種部署模式

模式:將服務部署為容器將作為容器鏡像打包的服務部署到生產環境中每個服務實例都是一個容器。

創建容器時,可以指定它的CPU和內存資源,以及依賴於容器實現的I/O資源等。容器運行時強制執行這些限制,並防止容器佔用其機器的資源。使用 Docker編排框架(如 Kubernetes)時,指定容器的資源尤為重要。這是因為編排框架使用容器請求的資源來選擇運行容器的底層機器,從而確保機器不會過載。 在構建服務時,部署流水線使用容器鏡像構建工具,該工具讀取服務代碼和鏡像描述,以創建容器鏡像並將其存儲在鏡像倉庫中。在運行時,從鏡像倉庫中拉取容器鏡像,並用於創建容器。


使Docker用部署服務

要將服務部署為容器,必須將其打包為容器鏡像。容器鏡像是由應用程序和運行服務所需的依賴軟件組成的文件系統鏡像。它通常是一個完整的 Linux根文件系統,但更輕量級的鏡像也可以使用。例如,要部署基於 Spring Boot的服務,需要構建一個容器鏡像,其中包含服務的可執行JAR和正確的JDK版本。同樣,部署 Java Web應用程序,需要構建一個包含WAR文件 Apache、 Tomcat和JDK的容器鏡像。主要分為以下步驟。

  1. 構建 Docker鏡像
  2. 將Docker鏡像推送到鏡像倉庫
  3. 運行Docker容器

將服務部署為容器的好處

將服務部署為容器有幾個好處。首先,容器具有虛擬機的許多好處:

  • 封裝技術棧,可以用容器的API實現對服務的管理。 服務實例是隔離的。
  • 服務實例的資源受到限制。

但與虛擬機不同,容器是一種輕量級技術容器鏡像通常可以很快構建。例如,只需幾秒就可以將 Spring Boot應用程序打包為容器鏡像。通過網絡傳輸容器鏡像也相對較快主要是因為僅傳輸所需要的鏡像層的子集。(這是因為 Docker鏡像具有所謂的分層文件系統,使得 Docker只需要通過網絡傳輸部分鏡像。鏡像的操作系統、Java運行時和應用程序位於不同的層中。 Docker只需要傳輸鏡像倉庫中不存在的那些層。因此,當 Docker只需移動應用程序層時,通過網絡傳輸鏡像特別快)。容器也可以很快啟動,因為沒有冗長的操作系統啟動過程。當容器啟動時,所運行的就是服務。

將服務部署為容器的弊端

容器的一個顯著弊端是,你需要承擔大量的容器鏡像管理工作。你必須負責給操作系統和運行時打補丁。此外,除非使用託管容器解決方案(如 Google Container Engine或awsECS),否則你必須管理容器基礎設施以及容器運行可能需要的虛擬機基礎設施。


分享到:


相關文章: