實踐中的微服務:從架構到部署


在本文中,我計划介紹微服務架構(MSA)的關鍵架構概念,以及如何在實踐中使用這些架構原理。

微服務是軟件體系結構領域最流行的流行語之一。 關於微服務的基礎知識和好處的學習材料很多,但是關於如何在現實的企業場景中使用微服務的資源很少。

在本文中,我將介紹微服務架構(MSA)的關鍵架構概念,以及如何在實踐中使用這些架構原理。

整體架構

企業軟件應用程序旨在滿足眾多業務需求;給定的軟件應用程序提供數百種功能,所有這些功能都堆積在單個整體應用程序中。例如,ERP,CRM和其他各種軟件系統被構建為具有數百種功能的整體。如此龐大的軟件應用程序的部署,故障排除,擴展和升級是一場噩夢。

面向服務的體系結構(SOA)旨在通過引入服務的概念,應用程序提供的相似功能的聚集和分組來克服某些上述限制。使用SOA,可以將軟件應用程序設計為粗粒度服務的組合。但是,在SOA中,服務范圍非常廣泛。這導致具有數十種操作(功能)的復雜而龐大的服務,以及復雜的消息格式和標准(例如:所有WS *標准)。

 

整體架構

在大多數情況下,SOA中的服務彼此獨立。 但是它們與所有其他服務一起部署在同一運行時中(考慮一下將多個Web應用程序部署到同一Tomcat實例中)。 與單片軟件應用程序相似,這些服務具有通過累積各種功能隨着時間而增長的習慣。 從字面上看,這將這些應用程序變成了與通用整體應用程序(如ERP)沒有區別的整體結構。 該圖顯示了包含多個服務的零售軟件應用程序。 所有這些服務都部署到同一應用程序運行時中。 因此,這是一個整體架構的很好的例子。 這是基於整體架構的應用程序的一些特征。

  • ·整體應用程序是作為一個單元進行設計,開發和部署的。
  • ·整體應用極為復雜; 這導致維護,升級和添加新功能的噩夢。
  • ·很難使用Monolithic體系結構來實踐敏捷開發和交付方法。
  • ·需要重新部署整個應用程序以更新其中的一部分。
  • ·該應用程序必須按單個單元進行擴展,從而難以管理相互沖突的資源需求(例如,一項服務需要更多的CPU,而另一項則需要更多的內存)
  • ·一項不穩定的服務可能會導致整個應用程序崩潰。
  • ·采用新技術和框架真的很困難,因為所有功能都必須基於同類技術/框架。

微服務架構

微服務架構(MSA)的基礎是將單個應用程序開發為一組小型獨立服務,這些獨立服務在其自己的流程中運行,獨立開發和部署。

在微服務架構的大多數定義中,將其解釋為將整體中可用的服務隔離為一組獨立服務的過程。但是,在我看來,微服務不僅僅是將整體中可用的服務拆分為獨立的服務。

關鍵思想是,通過查看整體提供的功能,我們可以確定所需的業務能力。然后,可以將那些業務功能實現為完全獨立,細粒度且自包含的(微)服務。它們可能在不同的技術堆棧之上實現,並且每種服務都針對非常特定且有限的業務范圍。

因此,我們上面解釋的在線零售系統場景可以通過微服務架構實現,如下圖所示。通過微服務體系結構,零售軟件應用程序被實現為一組微服務。因此,正如在下面看到的那樣,根據業務需求,還有一個整體服務是根據整體中存在的原始服務集創建的。因此,很明顯,使用微服務體系結構是超出了整體中服務拆分的范圍。

 

微服務架構

讓我們深入研究微服務的關鍵體系結構原理,更重要的是,讓我們集中討論如何在實踐中使用它們。

設計微服務:大小,范圍和功能

可能正在使用Microservices Architecture從頭開始構建軟件應用程序,或者可能將現有的應用程序/服務轉換為微服務。 無論哪種方式,正確決定微服務的大小,范圍和功能都是非常重要的。 這可能是在實踐中實現微服務架構時最初遇到的最困難的事情。

讓我們討論與微服務的大小,范圍和功能有關的一些關鍵的實際問題和誤解。

  • ·代碼行/團隊規模是糟糕的指標:關於基於實現的代碼行或團隊規模(即兩個比薩餅團隊)確定微服務規模的討論很多。 但是,這些指標被認為是非常不切實際和糟糕的指標,因為我們仍然可以使用更少的代碼/具有兩個比薩餅的團隊來開發服務,但完全違反了微服務架構的原則。
  • ·“微”是一個誤導性術語:大多數開發人員傾向於認為他們應該嘗試使服務盡可能小。 這是一個誤解。
  • ·SOA上下文:在SOA上下文中,服務通常實現為整體,並支持數十種操作/功能。 因此,擁有類似於SOA的服務並將其重新命名為微服務並不會給帶來微服務架構的任何好處。

那么,我們應該如何在微服務架構中正確設計服務?

設計微服務准則

  • ·“單一責任原則”(SRP):微服務的業務范圍有限且重點突出,可以幫助我們滿足服務開發和交付中的敏捷性。
  • ·在微服務的設計階段,我們應該找到它們的邊界並將其與業務功能(在域驅動設計中也稱為受限上下文)保持一致。
  • ·確保微服務設計可確保服務的敏捷/獨立開發和部署。
  • ·我們的重點應該放在微服務的范圍上,而不是縮小服務范圍。 服務的(正確)大小應該是促進給定業務能力所需的大小。
  • ·與SOA中的服務不同,給定的微服務應具有很少的操作/功能和簡單的消息格式。
  • ·通常,從較長的服務邊界開始,然后隨着時間的流逝而重構為較小的服務邊界(根據業務需求)通常是一個好習慣。

在我們的零售用例中,可以發現我們已經將整體的功能分為四個不同的微服務,即“庫存”,“會計”,“運輸”和“商店”。 他們正在解決一個有限但集中的業務范圍,以便每個服務彼此完全分離,並確保開發和部署的敏捷性。

微服務中的消息傳遞

在單片應用程序中,使用功能調用或語言級方法調用來調用不同處理器/組件的業務功能。 在SOA中,這已轉向更加松散耦合的Web服務級別消息傳遞,該消息傳遞主要基於SOAP並基於HTTP,JMS等不同協議。 具有數十種操作和復雜消息模式的Web服務是Web服務普及的主要阻力。 對於微服務架構,要求具有簡單輕量的消息傳遞機制。

同步消息傳遞-REST,節流

對於Microservices Architecture中的同步消息傳遞(客戶端希望服務及時響應並等待它獲得響應),REST是一致的選擇,因為它提供了一種簡單的消息傳遞樣式,該消息傳遞樣式基於資源API樣式通過HTTP請求響應實現。 因此,大多數微服務實現都使用HTTP以及基於資源API的樣式(每種功能都由一種資源表示,並且在這些資源之上執行操作)。

 

使用REST接口公開微服務

使用Thrift(你可以在其中定義微服務的接口定義),作為REST / HTTP同步消息傳遞的替代方法。

異步消息傳遞-AMQP,STOMP,MQTT

對於某些微服務場景,要求使用異步消息傳遞技術(客戶端不希望立即響應,或者根本不接受響應)。 在這種情況下,異步消息傳遞協議如AMQP,STOMP或MQTT被廣泛使用。

消息格式-JSON,XML,Thrift,ProtoBuf,Avro

roservices是另一個關鍵因素。 傳統的單片應用程序使用復雜的二進制格式,基於SOA / Web服務的應用程序使用基於復雜消息格式(SOAP)和架構(xsd)的文本消息。 在大多數基於微服務的應用程序中,它們使用簡單的基於文本的消息格式,例如HTTP資源API樣式之上的JSON和XML。 在我們需要二進制消息格式的情況下(文本消息在某些用例中可能變得冗長),微服務可以利用二進制消息格式,例如二進制Thrift,ProtoBuf或Avro。

服務合同-定義服務接口-Swagger,RAML,節儉

將業務功能實現為服務時,需要定義和發布服務合同。 在傳統的整體應用程序中,我們幾乎找不到用於定義應用程序業務功能的功能。 SOA / Web服務世界中,WSDL用於定義服務協定,但是,眾所周知,WSDL並不是復雜的且與SOAP緊密耦合,因此不是定義微服務協定的理想解決方案。

由於我們是基於REST架構樣式構建微服務的,因此我們可以使用相同的REST API定義技術來定義微服務的契約。 因此,微服務使用標准的REST API定義語言(例如Swagger和RAML)來定義服務合同。

對於其他不基於HTTP / REST的微服務實現(例如Thrift),我們可以使用協議級別的接口定義語言(IDL)(例如:Thrift IDL)。

集成微服務(服務間/流程通信)

在微服務體系結構中,軟件應用程序被構建為一套獨立的服務。因此,為了實現業務用例,需要在不同的微服務/流程之間具有通信結構。這就是微服務之間的服務間/流程通信如此重要的原因。

SOA實現中,使用企業服務總線(ESB)可以促進服務之間的服務間通信,並且大多數業務邏輯位於中間層(消息路由,轉換和編排)。但是,微服務體系結構促進消除中央消息總線/ ESB,並將“智能性”或業務邏輯轉移到服務和客戶端(稱為智能端點)。

由於微服務使用諸如HTTP,JSON等標准協議,因此在微服務​​之間進行通信時,與不同協議集成的要求極小。微服務通信中的另一種替代方法是使用輕量級消息總線或網關,路由功能最少,並充當``啞管道'',而網關上未實現任何業務邏輯。基於這些樣式,微服務體系結構中出現了幾種通信模式。

點對點樣式-直接調用服務

在點對點樣式中,整個消息路由邏輯都駐留在每個端點上,並且服務可以直接進行通信。 每個微服務都公開一個REST API,給定的微服務或外部客戶端可以通過其REST API調用另一個微服務。

 

具有點對點連接的服務間通信

顯然,該模型適用於相對簡單的基於微服務的應用程序,但是隨着服務數量的增加,這將變得極為復雜。 畢竟,這就是在傳統SOA實現中使用ESB的確切原因:擺脫凌亂的點對點集成鏈接。 讓我們嘗試總結微服務通信的點對點樣式的主要缺點。

  • ·必須在每個微服務級別實現最終用戶身份驗證,限制,監視等非功能性要求。
  • ·由於復制了通用功能,因此每個微服務實現都可能變得復雜。
  • ·服務與客戶端之間的所有通信都無法控制(即使用於監視,跟蹤或篩選)
  • ·對於大規模微服務實現,通常將直接通信樣式視為微服務反模式。

因此,對於復雜的微服務用例,我們可以使用輕量級的中央消息傳遞總線,而不是使用點對點連接或中央ESB,它可以為微服務提供抽象層,並可以用於實現各種非功能性 能力。 此樣式稱為API網關樣式

API網關樣式

API網關樣式背后的關鍵思想是使用輕量級消息網關作為所有客戶端/消費者的主要入口點,並在網關級別實現常見的非功能性要求。 通常,API網關允許通過REST / HTTP使用托管API。 因此,在這里,我們可以將通過API-GW作為托管服務實現為微服務的業務功能公開。 實際上,這是微服務架構和API管理的結合,可為提供兩全其美的體驗。

所有微服務都通過API-GW公開在我們的零售業務場景中,如上圖所示,所有微服務都通過API-GW公開,這是所有客戶端的單一入口點。 如果微服務想要使用另一個微服務,則也需要通過API-GW來完成。

API-GW樣式具有以下優點:

  • ·能夠在網關級別為現有微服務提供所需的抽象。 例如,API網關可以提供每個客戶端不同的API,而不是提供一種千篇一律的樣式API
  • ·網關級別的輕量級消息路由/轉換。
  • ·應用非功能性功能(例如安全性,監視和限制)的中心位置。
  • ·通過使用API-GW模式,由於所有非功能性需求都在網關級別實現,因此微服務變得更加輕量級。

API-GW樣式很可能是大多數微服務實現中使用最廣泛的模式。

消息代理樣式

微服務可以與異步消息傳遞場景集成,例如單向請求和使用隊列或主題的發布-訂閱消息傳遞。 給定的微服務可以是消息生產者,並且可以異步將消息發送到隊列或主題。 然后,消費微服務可以消費來自隊列或主題的消息。 這種樣式使消息生產者與消息使用者分離,中間消息代理將緩沖消息,直到使用者能夠處理它們為止。 生產者微服務完全不了解消費者微服務。

使用pub-sub的基於異步消息傳遞的集成

消費者/生產者之間的通信通過基於異步消息傳遞標准(例如AMQP,MQTT等)的消息代理來促進。

分散數據管理

在整體架構中,應用程序將數據存儲在單個集中式數據庫中,以實現應用程序的各種功能。

單一應用程序使用中央數據庫來實現其所有功能。在微服務體系結構中,功能分散在多個微服務之間,如果我們使用相同的中央數據庫,則微服務將不再彼此獨立(例如,如果 數據庫架構已從給定的微服務更改,這將破壞其他幾個服務)。 因此,每個微服務都必須具有自己的數據庫。

每個微服務都有自己的私有數據庫

這是在微服務架構中實施分散數據管理的關鍵方面。

  • ·每個微服務都可以有一個私有數據庫來保留實現其提供的業務功能所需的數據。
  • ·給定的微服務只能訪問專用私有數據庫,而不能訪問其他微服務的數據庫。
  • ·在某些業務場景中,你可能必須為單個事務更新多個數據庫。 在這種情況下,其他微服務的數據庫應僅通過其服務API進行更新(不允許直接訪問該數據庫)

分散的數據管理為你提供了完全解耦的微服務,並且可以自由選擇不同的數據管理技術(SQLNoSQL等,每種服務使用不同的數據庫管理系統)。 但是,對於涉及多個微服務的復雜事務用例,必須使用每個服務提供的API來實現事務行為,並且邏輯位於客戶端或中介(GW)級別。

分散治理

微服務架構支持分散式治理。

  • 通常,“治理”是指建立和加強人員和解決方案如何共同協作以實現組織目標。 在SOA的背景下,SOA治理指導可重用服務的開發,確定如何設計和開發服務以及這些服務將隨着時間的變化而變化。 它在服務的提供者和這些服務的消費者之間建立協議,告訴消費者他們可以期望什么以及提供者他們有義務提供什么。 在SOA治理中,有兩種常用的治理類型:

那么,微服務環境中的治理到底意味着什么? 在微服務架構中,微服務被構建為具有各種技術和平台的完全獨立和解耦的服務。 因此,無需為服務設計和開發定義通用標准。 因此,我們可以將微服務的去中心化治理功能總結如下:

  • ·在微服務架構中,不需要進行集中的設計時治理。
  • ·微服務可以自行決定其設計和實現。
  • ·微服務架構促進了公共/可重用服務的共享。
  • ·某些運行時治理方面,例如SLA,節流,監視,通用安全要求和服務發現,可以在API-GW級別上實現。

服務注冊和服務發現

在微服務架構中,你需要處理的微服務數量非常多。而且,由於微服務的快速和敏捷開發/部署性質,它們的位置會動態變化。因此,你需要在運行時找到微服務的位置。解決此問題的方法是使用服務注冊表。

服務注冊

服務注冊表包含微服務實例及其位置。微服務實例在啟動時在服務注冊表中注冊,並在關機時注銷。消費者可以通過服務注冊表找到可用的微服務及其位置。

服務發現

為了找到可用的微服務及其位置,我們需要一種服務發現機制。服務發現機制有兩種類型,客戶端發現和服務器端發現。讓我們仔細看看那些服務發現機制。

客戶端發現-通過這種方法,客戶端或API-GW通過查詢服務注冊表來獲取服務實例的位置。

在微服務架構中,你需要處理的微服務數量非常多。 而且,由於微服務的快速和敏捷開發/部署性質,它們的位置會動態變化。 因此,需要在運行時找到微服務的位置。 解決此問題的方法是使用服務注冊表。

服務注冊

服務注冊表包含微服務實例及其位置。 微服務實例在啟動時在服務注冊表中注冊,並在關機時注銷。 消費者可以通過服務注冊表找到可用的微服務及其位置。

服務發現

為了找到可用的微服務及其位置,我們需要一種服務發現機制。 服務發現機制有兩種類型,客戶端發現和服務器端發現。 讓我們仔細看看那些服務發現機制。

客戶端發現-通過這種方法,客戶端或API-GW通過查詢服務注冊表來獲取服務實例的位置。

客戶端發現

服務器端發現-使用這種方法,客戶端/ API-GW將請求發送到在已知位置運行的組件(例如負載均衡器)。 該組件調用服務注冊表並確定微服務的絕對位置。

客戶端發現

諸如Kubernetes(http://kubernetes.io/v1.1/docs/user-guide/services.html)之類的微服務部署解決方案提供了服務端發現機制。

部署方式

在微服務架構方面,微服務的部署起着至關重要的作用,並且具有以下關鍵要求:

  • 能夠獨立於其他微服務進行部署/取消部署。
  • 必須能夠在每個微服務級別進行擴展(給定的服務可能比其他服務獲得更多的流量)。
  • 快速構建和部署微服務。
  • 一個微服務中的故障不得影響任何其他服務。

Docker(一種開放源代碼引擎,可讓開發人員和系統管理員在Linux環境中部署自給自足的應用程序容器)提供了一種很好的方式來部署微服務以滿足上述要求。 涉及的關鍵步驟如下:

  • ·將微服務打包為(Docker)容器映像。
  • ·將每個服務實例部署為一個容器。
  • ·縮放是根據更改容器實例的數量完成的。
  • ·隨着我們使用Docker容器,構建,部署和啟動微服務的速度將大大提高(比常規VM快得多)

Kubernetes通過允許將Linux容器集群作為一個系統進行管理,跨多個主機管理和運行Docker容器,提供容器的共置,服務發現和復制控制功能,擴展了Docker的功能。 如所見,大多數這些功能在我們的微服務環境中也是必不可少的。 因此,使用Kubernetes(在Docker之上)進行微服務部署已成為一種極其強大的方法,尤其是對於大規模微服務部署。

將微服務構建和部署為容器。

在上圖中,它顯示了零售應用程序的微服務部署的概述。 每個微服務實例都作為一個容器部署,每個主機有兩個容器。 你可以任意更改在給定主機上運行的容器的數量。

安全

在實際場景中使用微服務時,保護微服務是非常普遍的要求。 在進入微服務安全性之前,讓我們快速看一下我們通常如何在整體應用程序級別上實現安全性。

  • 在典型的整體應用程序中,安全性是要找到“誰是呼叫者”,“呼叫者能做什么”和“我們如何傳播該信息”。
  • 這通常是在請求處理鏈的開始處的通用安全組件上實現的,並且該組件使用基礎用戶存儲庫(或用戶存儲)填充所需的信息。

那么,我們可以直接將此模式轉換為微服務架構嗎? 是的,但這需要在每個微服務級別實現的安全組件,該組件正在與集中式/共享用戶存儲庫進行對話並檢索所需的信息。 這是解決微服務安全性問題的非常乏味的方法。 相反,我們可以利用廣泛使用的API安全標准(例如OAuth2OpenID Connect)為我們的微服務安全問題找到更好的解決方案。 在深入探討這一點之前,讓我概述一下每個標准的目的以及如何使用它們

  • ·OAuth2-是訪問委派協議。 客戶端通過授權服務器進行身份驗證,並獲得一個不透明的令牌,稱為“訪問令牌”。 訪問令牌的用戶/客戶端信息為零。 它僅具有對只能由授權服務器檢索的用戶信息的引用。 因此,這被稱為“參考令牌”,即使在公共網絡/互聯網中也可以安全地使用此令牌。

·OpenIDConnect的行為類似於OAuth,但除了訪問令牌外,授權服務器還會發布一個ID令牌,其中包含有關用戶的信息。 這通常由JWTJSON Web令牌)實現,並由授權服務器簽名。 因此,這確保了授權服務器和客戶端之間的信任。 因此,JWT令牌被稱為“按值令牌”,因為它包含用戶的信息,並且顯然在內部網絡之外使用它是不安全的。

具有OAuth2和OpenID Connect的微服務安全性

如上圖所示,這些是實現微服務安全性涉及的關鍵步驟:

  • ·將身份驗證留給OAuthOpenID Connect服務器(授權服務器),以便在有人有權使用數據的情況下,微服務成功提供訪問權限。
  • ·使用API​​-GW樣式,在該樣式中,所有客戶端請求都有一個入口點。
  • 客戶端連接到授權服務器並獲得訪問令牌(按引用令牌)。然后將訪問令牌與請求一起發送到API-GW
  • 網關上的令牌轉換-API-GW提取訪問令牌並將其發送到授權服務器以檢索JWT(按值令牌)。
  • ·然后,GW將這個JWT與請求一起傳遞給微服務層。
  • ·JWT包含必要的信息,以幫助存儲用戶會話等。如果每個服務都可以理解JSON Web令牌,則你已經分發了身份識別機制,該機制允許你在整個系統中傳輸身份。
  • 在每個微服務層,我們可以有一個處理JWT的組件,這是一個非常簡單的實現。

交易次數

微服務中的交易支持如何?實際上,支持跨多個微服務的分布式事務是非常復雜的任務。微服務架構本身鼓勵服務之間的無事務協調。

想法是,給定的服務是完全獨立的,並且基於單一責任原則。跨多個微服務進行分布式事務的需求通常是微服務體系結構中設計缺陷的征兆,通常可以通過重構微服務的范圍來解決。但是,如果必須在多個服務之間分配事務,則可以通過在每個微服務級別引入“補償操作”來實現這種情況。關鍵思想是,給定的微服務基於單一職責原則,如果給定的微服務無法執行給定的操作,我們可以認為這是整個微服務的失敗。然后,必須通過調用這些微服務的相應補償操作來撤消所有其他(上游)操作。

失敗的設計

微服務架構引入了一組分散的服務,並且與單片設計相比,增加了在每個服務級別出現故障的可能性。 給定的微服務可能會由於網絡問題,基礎資源的不可用等原因而失敗。不可用或無響應的微服務不應導致整個基於微服務的應用程序崩潰。 因此,微服務應該是容錯的,能夠在可能的情況下恢復,並且客戶端必須妥善處理它。

另外,由於服務隨時可能發生故障,因此能夠快速檢測(實時監視)故障並在可能的情況下自動恢復服務也很重要。

在微服務上下文中,有幾種常用的模式來處理錯誤。context.

斷路器

當你對微服務進行外部調用時,你需要為每次調用配置一個故障監視器組件,並且當故障達到某個閾值時,該組件將停止對該服務的任何進一步調用(使電路跳閘)。 在一定數量的請求處於打開狀態(你可以配置)之后,將電路更改回關閉狀態。

這種模式非常有用,可避免不必要的資源消耗,由於超時而導致的請求延遲,並且還使我們有機會監視系統(基於活動的開路狀態)。

隔板

由於微服務應用程序包含微服務的數量,因此基於微服務的應用程序一部分的故障不應影響其余的應用程序。 隔板模式是關於隔離應用程序的不同部分的,因此應用程序中服務的故障不會影響任何其他服務。

暫停

超時模式是一種機制,當你認為微服務不會響應時,它可以讓你停止等待微服務的響應。 你可以在此處配置希望等待的時間間隔。

那么,我們在哪里以及如何在微服務中使用這些模式? 在大多數情況下,這些模式中的大多數都適用於網關級別。 這意味着當微服務不可用或沒有響應時,在網關級別,我們可以決定是否使用斷路器或超時模式將請求發送到微服務。 同樣,在網關級別實現諸如隔板等模式也是非常重要的,因為它是所有客戶端請求的單個入口點,因此贈與服務的失敗不應影響其他微服務的調用。

另外,網關可以用作中心點,當通過網關調用每個微服務時,我們可以獲得狀態並監視每個微服務。

微服務,企業集成,API管理等

我們已經討論了微服務架構的各種特征,以及如何在現代企業IT環境中實現它們。但是,我們應該記住,微服務不是萬能葯。流行語概念的盲目適應將無法解決“實際”企業IT問題。正如在整個博客文章中所看到的那樣,微服務具有很多優勢,我們應該加以利用。但是,我們還必須記住,用微服務解決所有企業IT問題是不現實的。例如,微服務架構促進了消除ESB作為中央總線的發展,但是在現實世界中,有很多不基於微服務的現有應用程序/服務。因此,要與它們集成,我們需要某種集成總線。因此,理想情況下,微服務和其他企業體系結構概念(例如集成)的混合方法將更為現實。我將在另一篇博客文章中進一步討論它們。

本文靈感源於優銳課java架構學習分享,希望這使你對如何在企業中使用微服務有了更清晰的認識。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM