在本文中,我計劃介紹微服務架構(MSA)的關鍵架構概念,以及如何在實踐中使用這些架構原理。html
微服務是軟件體系結構領域最流行的流行語之一。 關於微服務的基礎知識和好處的學習材料不少,可是關於如何在現實的企業場景中使用微服務的資源不多。java
在本文中,我將介紹微服務架構(MSA)的關鍵架構概念,以及如何在實踐中使用這些架構原理。數據庫
總體架構安全
企業軟件應用程序旨在知足衆多業務需求;給定的軟件應用程序提供數百種功能,全部這些功能都堆積在單個總體應用程序中。例如,ERP,CRM和其餘各類軟件系統被構建爲具備數百種功能的總體。如此龐大的軟件應用程序的部署,故障排除,擴展和升級是一場噩夢。服務器
面向服務的體系結構(SOA)旨在經過引入服務的概念,應用程序提供的類似功能的彙集和分組來克服某些上述限制。使用SOA,能夠將軟件應用程序設計爲粗粒度服務的組合。可是,在SOA中,服務範圍很是普遍。這致使具備數十種操做(功能)的複雜而龐大的服務,以及複雜的消息格式和標準(例如:全部WS *標準)。網絡
總體架構架構
在大多數狀況下,SOA中的服務彼此獨立。 可是它們與全部其餘服務一塊兒部署在同一運行時中(考慮一下將多個Web應用程序部署到同一Tomcat實例中)。 與單片軟件應用程序類似,這些服務具備經過累積各類功能隨着時間而增加的習慣。 從字面上看,這將這些應用程序變成了與通用總體應用程序(如ERP)沒有區別的總體結構。 該圖顯示了包含多個服務的零售軟件應用程序。 全部這些服務都部署到同一應用程序運行時中。 所以,這是一個總體架構的很好的例子。 這是基於總體架構的應用程序的一些特徵。負載均衡
微服務架構(MSA)的基礎是將單個應用程序開發爲一組小型獨立服務,這些獨立服務在其本身的流程中運行,獨立開發和部署。框架
在微服務架構的大多數定義中,將其解釋爲將總體中可用的服務隔離爲一組獨立服務的過程。可是,在我看來,微服務不只僅是將總體中可用的服務拆分爲獨立的服務。異步
關鍵思想是,經過查看總體提供的功能,咱們能夠肯定所需的業務能力。而後,能夠將那些業務功能實現爲徹底獨立,細粒度且自包含的(微)服務。它們可能在不一樣的技術堆棧之上實現,而且每種服務都針對很是特定且有限的業務範圍。
所以,咱們上面解釋的在線零售系統場景能夠經過微服務架構實現,以下圖所示。經過微服務體系結構,零售軟件應用程序被實現爲一組微服務。所以,正如你在下面看到的那樣,根據業務需求,還有一個總體服務是根據總體中存在的原始服務集建立的。所以,很明顯,使用微服務體系結構是超出了總體中服務拆分的範圍。
微服務架構
讓咱們深刻研究微服務的關鍵體系結構原理,更重要的是,讓咱們集中討論如何在實踐中使用它們。
你可能正在使用Microservices Architecture從頭開始構建軟件應用程序,或者可能將現有的應用程序/服務轉換爲微服務。 不管哪一種方式,正確決定微服務的大小,範圍和功能都是很是重要的。 這多是你在實踐中實現微服務架構時最初遇到的最困難的事情。
讓咱們討論與微服務的大小,範圍和功能有關的一些關鍵的實際問題和誤解。
那麼,咱們應該如何在微服務架構中正確設計服務?
在咱們的零售用例中,你能夠發現咱們已經將總體的功能分爲四個不一樣的微服務,即「庫存」,「會計」,「運輸」和「商店」。 他們正在解決一個有限但集中的業務範圍,以便每一個服務彼此徹底分離,並確保開發和部署的敏捷性。
在單片應用程序中,使用功能調用或語言級方法調用來調用不一樣處理器/組件的業務功能。 在SOA中,這已轉向更加鬆散耦合的Web服務級別消息傳遞,該消息傳遞主要基於SOAP並基於HTTP,JMS等不一樣協議。 具備數十種操做和複雜消息模式的Web服務是Web服務普及的主要阻力。 對於微服務架構,要求具備簡單輕量的消息傳遞機制。
對於Microservices Architecture中的同步消息傳遞(客戶端但願服務及時響應並等待它得到響應),REST是一致的選擇,由於它提供了一種簡單的消息傳遞樣式,該消息傳遞樣式基於資源API樣式經過HTTP請求響應實現。 所以,大多數微服務實現都使用HTTP以及基於資源API的樣式(每種功能都由一種資源表示,而且在這些資源之上執行操做)。
對於某些微服務場景,要求使用異步消息傳遞技術(客戶端不但願當即響應,或者根本不接受響應)。 在這種狀況下,異步消息傳遞協議如AMQP,STOMP或MQTT被普遍使用。
消息格式-JSON,XML,Thrift,ProtoBuf,Avro
roservices是另外一個關鍵因素。 傳統的單片應用程序使用複雜的二進制格式,基於SOA / Web服務的應用程序使用基於複雜消息格式(SOAP)和架構(xsd)的文本消息。 在大多數基於微服務的應用程序中,它們使用簡單的基於文本的消息格式,例如HTTP資源API樣式之上的JSON和XML。 在咱們須要二進制消息格式的狀況下(文本消息在某些用例中可能變得冗長),微服務能夠利用二進制消息格式,例如二進制Thrift,ProtoBuf或Avro。
當你將業務功能實現爲服務時,你須要定義和發佈服務合同。 在傳統的總體應用程序中,咱們幾乎找不到用於定義應用程序業務功能的功能。 在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的確切緣由:擺脫凌亂的點對點集成連接。 讓咱們嘗試總結微服務通訊的點對點樣式的主要缺點。
API網關樣式背後的關鍵思想是使用輕量級消息網關做爲全部客戶端/消費者的主要入口點,並在網關級別實現常見的非功能性要求。 一般,API網關容許你經過REST / HTTP使用託管API。 所以,在這裏,咱們能夠將經過API-GW做爲託管服務實現爲微服務的業務功能公開。 實際上,這是微服務架構和API管理的結合,可爲你提供一箭雙鵰的體驗。
全部微服務都經過API-GW公開在咱們的零售業務場景中,如上圖所示,全部微服務都經過API-GW公開,這是全部客戶端的單一入口點。 若是微服務想要使用另外一個微服務,則也須要經過API-GW來完成。
API-GW樣式具備如下優勢:
API-GW樣式極可能是大多數微服務實現中使用最普遍的模式。
微服務能夠與異步消息傳遞場景集成,例如單向請求和使用隊列或主題的發佈-訂閱消息傳遞。 給定的微服務能夠是消息生產者,而且能夠異步將消息發送到隊列或主題。 而後,消費微服務能夠消費來自隊列或主題的消息。 這種樣式使消息生產者與消息使用者分離,中間消息代理將緩衝消息,直到使用者可以處理它們爲止。 生產者微服務徹底不瞭解消費者微服務。
使用pub-sub的基於異步消息傳遞的集成
消費者/生產者之間的通訊經過基於異步消息傳遞標準(例如AMQP,MQTT等)的消息代理來促進。
在總體架構中,應用程序將數據存儲在單個集中式數據庫中,以實現應用程序的各類功能。
單一應用程序使用中央數據庫來實現其全部功能。在微服務體系結構中,功能分散在多個微服務之間,若是咱們使用相同的中央數據庫,則微服務將再也不彼此獨立(例如,若是 數據庫架構已從給定的微服務更改,這將破壞其餘幾個服務)。 所以,每一個微服務都必須具備本身的數據庫。
每一個微服務都有本身的私有數據庫
這是在微服務架構中實施分散數據管理的關鍵方面。
分散的數據管理爲你提供了徹底解耦的微服務,而且能夠自由選擇不一樣的數據管理技術(SQL或NoSQL等,每種服務使用不一樣的數據庫管理系統)。 可是,對於涉及多個微服務的復瑣事務用例,必須使用每一個服務提供的API來實現事務行爲,而且邏輯位於客戶端或中介(GW)級別。
微服務架構支持分散式治理。
那麼,微服務環境中的治理到底意味着什麼? 在微服務架構中,微服務被構建爲具備各類技術和平臺的徹底獨立和解耦的服務。 所以,無需爲服務設計和開發定義通用標準。 所以,咱們能夠將微服務的去中心化治理功能總結以下:
在微服務架構中,你須要處理的微服務數量很是多。並且,因爲微服務的快速和敏捷開發/部署性質,它們的位置會動態變化。所以,你須要在運行時找到微服務的位置。解決此問題的方法是使用服務註冊表。
服務註冊
服務註冊表包含微服務實例及其位置。微服務實例在啓動時在服務註冊表中註冊,並在關機時註銷。消費者能夠經過服務註冊表找到可用的微服務及其位置。
服務發現
爲了找到可用的微服務及其位置,咱們須要一種服務發現機制。服務發現機制有兩種類型,客戶端發現和服務器端發現。讓咱們仔細看看那些服務發現機制。
客戶端發現-經過這種方法,客戶端或API-GW經過查詢服務註冊表來獲取服務實例的位置。
在微服務架構中,你須要處理的微服務數量很是多。 並且,因爲微服務的快速和敏捷開發/部署性質,它們的位置會動態變化。 所以,你須要在運行時找到微服務的位置。 解決此問題的方法是使用服務註冊表。
服務註冊
服務註冊表包含微服務實例及其位置。 微服務實例在啓動時在服務註冊表中註冊,並在關機時註銷。 消費者能夠經過服務註冊表找到可用的微服務及其位置。
爲了找到可用的微服務及其位置,咱們須要一種服務發現機制。 服務發現機制有兩種類型,客戶端發現和服務器端發現。 讓咱們仔細看看那些服務發現機制。
客戶端發現-經過這種方法,客戶端或API-GW經過查詢服務註冊表來獲取服務實例的位置。
客戶端發現
服務器端發現-使用這種方法,客戶端/ API-GW將請求發送到在已知位置運行的組件(例如負載均衡器)。 該組件調用服務註冊表並肯定微服務的絕對位置。
客戶端發現
諸如Kubernetes(http://kubernetes.io/v1.1/docs/user-guide/services.html)之類的微服務部署解決方案提供了服務端發現機制。
在微服務架構方面,微服務的部署起着相當重要的做用,而且具備如下關鍵要求:
Docker(一種開放源代碼引擎,可以讓開發人員和系統管理員在Linux環境中部署自給自足的應用程序容器)提供了一種很好的方式來部署微服務以知足上述要求。 涉及的關鍵步驟以下:
Kubernetes經過容許將Linux容器集羣做爲一個系統進行管理,跨多個主機管理和運行Docker容器,提供容器的共置,服務發現和複製控制功能,擴展了Docker的功能。 如你所見,大多數這些功能在咱們的微服務環境中也是必不可少的。 所以,使用Kubernetes(在Docker之上)進行微服務部署已成爲一種極其強大的方法,尤爲是對於大規模微服務部署。
將微服務構建和部署爲容器。
在實際場景中使用微服務時,保護微服務是很是廣泛的要求。 在進入微服務安全性以前,讓咱們快速看一下咱們一般如何在總體應用程序級別上實現安全性。
那麼,咱們能夠直接將此模式轉換爲微服務架構嗎? 是的,但這須要在每一個微服務級別實現的安全組件,該組件正在與集中式/共享用戶存儲庫進行對話並檢索所需的信息。 這是解決微服務安全性問題的很是乏味的方法。 相反,咱們能夠利用普遍使用的API安全標準(例如OAuth2和OpenID Connect)爲咱們的微服務安全問題找到更好的解決方案。 在深刻探討這一點以前,讓我概述一下每一個標準的目的以及如何使用它們
·OpenIDConnect的行爲相似於OAuth,但除了訪問令牌外,受權服務器還會發佈一個ID令牌,其中包含有關用戶的信息。 這一般由JWT(JSON Web令牌)實現,並由受權服務器簽名。 所以,這確保了受權服務器和客戶端之間的信任。 所以,JWT令牌被稱爲「按值令牌」,由於它包含用戶的信息,而且顯然在內部網絡以外使用它是不安全的。
具備OAuth2和OpenID Connect的微服務安全性
如上圖所示,這些是實現微服務安全性涉及的關鍵步驟:
微服務中的交易支持如何?實際上,支持跨多個微服務的分佈式事務是很是複雜的任務。微服務架構自己鼓勵服務之間的無事務協調。
想法是,給定的服務是徹底獨立的,而且基於單一責任原則。跨多個微服務進行分佈式事務的需求一般是微服務體系結構中設計缺陷的徵兆,一般能夠經過重構微服務的範圍來解決。可是,若是必須在多個服務之間分配事務,則能夠經過在每一個微服務級別引入「補償操做」來實現這種狀況。關鍵思想是,給定的微服務基於單一職責原則,若是給定的微服務沒法執行給定的操做,咱們能夠認爲這是整個微服務的失敗。而後,必須經過調用這些微服務的相應補償操做來撤消全部其餘(上游)操做。
失敗的設計
微服務架構引入了一組分散的服務,而且與單片設計相比,增長了在每一個服務級別出現故障的可能性。 給定的微服務可能會因爲網絡問題,基礎資源的不可用等緣由而失敗。不可用或無響應的微服務不該致使整個基於微服務的應用程序崩潰。 所以,微服務應該是容錯的,可以在可能的狀況下恢復,而且客戶端必須妥善處理它。
另外,因爲服務隨時可能發生故障,所以可以快速檢測(實時監視)故障並在可能的狀況下自動恢復服務也很重要。
在微服務上下文中,有幾種經常使用的模式來處理錯誤。context.
當你對微服務進行外部調用時,你須要爲每次調用配置一個故障監視器組件,而且當故障達到某個閾值時,該組件將中止對該服務的任何進一步調用(使電路跳閘)。 在必定數量的請求處於打開狀態(你能夠配置)以後,將電路更改回關閉狀態。
這種模式很是有用,可避免沒必要要的資源消耗,因爲超時而致使的請求延遲,而且還使咱們有機會監視系統(基於活動的開路狀態)。
因爲微服務應用程序包含微服務的數量,所以基於微服務的應用程序一部分的故障不該影響其他的應用程序。 隔板模式是關於隔離應用程序的不一樣部分的,所以應用程序中服務的故障不會影響任何其餘服務。
超時模式是一種機制,當你認爲微服務不會響應時,它可讓你中止等待微服務的響應。 你能夠在此處配置但願等待的時間間隔。
那麼,咱們在哪裏以及如何在微服務中使用這些模式? 在大多數狀況下,這些模式中的大多數都適用於網關級別。 這意味着當微服務不可用或沒有響應時,在網關級別,咱們能夠決定是否使用斷路器或超時模式將請求發送到微服務。 一樣,在網關級別實現諸如隔板等模式也是很是重要的,由於它是全部客戶端請求的單個入口點,所以贈與服務的失敗不該影響其餘微服務的調用。
另外,網關能夠用做中心點,當經過網關調用每一個微服務時,咱們能夠得到狀態並監視每一個微服務。
咱們已經討論了微服務架構的各類特徵,以及如何在現代企業IT環境中實現它們。可是,咱們應該記住,微服務不是萬能藥。流行語概念的盲目適應將沒法解決你的「實際」企業IT問題。正如你在整個博客文章中所看到的那樣,微服務具備不少優點,咱們應該加以利用。可是,咱們還必須記住,用微服務解決全部企業IT問題是不現實的。例如,微服務架構促進了消除ESB做爲中央總線的發展,可是在現實世界中,有不少不基於微服務的現有應用程序/服務。所以,要與它們集成,咱們須要某種集成總線。所以,理想狀況下,微服務和其餘企業體系結構概念(例如集成)的混合方法將更爲現實。我將在另外一篇博客文章中進一步討論它們。
本文靈感源於優銳課java架構學習分享,但願這使你對如何在企業中使用微服務有了更清晰的認識。