近幾年來,“微服務體系結構”這個術語出現了,它描述了將軟件應用程序設計為可獨立部署的服務套件的特定方式。盡管這種架構風格沒有確切的定義,但圍繞業務能力,自動化部署,智能終端以及數據的分散控制等方面存在着某些共同特征。
“微服務” - 這一個在軟件架構擁擠的街道上的又一個新名詞。盡管我們的自然傾向是以輕蔑的眼光來傳遞它,但這個術語描述了一種我們發現越來越吸引人的軟件系統風格。我們已經看到許多項目在過去幾年中都采用了這種風格,迄今為止的結果是積極的,因此對於我們的許多人來說,這正成為構建企業應用程序的默認風格。但可悲的是,沒有太多的信息去描述了微服務的風格以及如何去做。簡而言之,微服務架構風格是一種將單個應用程序作為一套小型服務來開發的方法,每個服務都運行在自己的進程中,並與輕量級機制(通常是HTTP、RPC調用資源API方式出現)進行通信。這些服務是圍繞業務功能構建的,可以通過全自動部署機制獨立部署。這些服務的集中管理最少,可以用不同的編程語言編寫,並使用不同的數據存儲技術。
單體應用示例圖 微服務示例圖
當我們要開始解釋什么是微服務風格時,將其與單體應用風格進行比較是非常有用的:我們可以將單一應用程序包含的所有功能構建為單一個單元(如單體應用示例圖所示)。企業應用程序通常建立在三個主要部分之上:一個客戶端用戶界面(由用戶計算機上的瀏覽器中運行的HTML頁面和JavaScript組成)數據庫(關系數據庫管理的許多表系統)和一個服務器端應用程序。服務器端應用程序將處理HTTP請求,執行業務邏輯,從數據庫檢索和更新數據,選擇並填充要發送到瀏覽器的HTML視圖。這個服務器端應用程序是一個龐然大物 - 一個邏輯上可執行文件。系統的任何更改都涉及構建和部署新版本的服務器端應用程序。這種單一的應用是構建這種系統的一種自然方式。處理請求的所有邏輯都在一個進程中運行,允許您使用語言的基本功能將應用程序划分為類庫,類,函數和名稱空間。謹慎操作時,您可以在開發人員的筆記本電腦上運行和測試應用程序,並使用部署管道來確保更改經過適當測試並部署到生產環境中。您可以通過在負載均器后面運行多個實例來橫向擴展整體。雖然單一應用程序取得很多成功案例,但越來越多的人感到沮喪 - 尤其是隨着更多應用程序部署到雲中。變更周期是連在一起的 - 對應用程序的一小部分進行更改,需要重建和部署整個整體。隨着時間的推移,通常很難保持良好的模塊化結構,這使得難以保持應該僅影響該模塊中的一個模塊的變化。擴展需要擴展整個應用程序,而不是擴展需要變更的那部分資源。
單體應用集群 微服務應用集群
這些挫敗感導致了微服務架構風格出現:將應用程序構建為服務套件。除了服務可獨立部署和擴展之外,每個服務還提供了一個牢固的模塊邊界,甚至允許用不同的編程語言編寫不同的服務。他們也可以由不同的團隊管理。我並不認為微服務風格是新穎的或創新的,它的根源至少可以追溯到Unix的設計原則。但目前我認為沒有足夠多的人考慮微服務架構,並且許多軟件開發如果使用它們會更好。
微服務架構的特點
我們不能說微服務架構風格已經有了一個正式的定義,但我可以試圖描述我們認為符合標准的架構的共同特征。與其他常見特性的任何定義一樣,並非所有微服務架構都具有所有特性,但我們確實期望大多數微服務架構具有大多數特性。我們的目的是試圖描述在自己的工作中所看到的以及所了解的團隊的類似努力。特別是我們並沒有制定一些符合的定義。
通過服務進行組件化
自從我們進入軟件行業以來,就一直希望通過將組件整合在一起來構建系統,這與我們在現實世界中看到事物的方式非常相似。在談論組件時,遇到了構成組件的困難定義。我們的定義是, 組件是可獨立更換和升級的軟件單元。微服務體系結構也使用類似庫包裝的概念,但是它們組裝自己軟件的主要方式是分解為服務。我們將庫定義為鏈接到程序中的組件,並使用內存中的函數調用進行調用,而服務是與Web服務請求或遠程過程調用等機制進行通信的進程外組件。(這與許多面向對象程序中服務對象的概念不同。使用服務作為組件(而不是庫)的一個主要原因是服務可獨立部署。如果您的應用程序由單個進程中的多個庫組成,那么對任何單個組件的更改都會導致必須重新部署整個應用程序。但是,如果該應用程序分解為多個服務,則可以期望許多單一服務更改只需要重新部署該部分服務。但這不是絕對的,有些改變會改變服務接口,導致一些協調,但是一個好的微服務架構的目標是通過服務合約中的內聚服務邊界和進化機制來最小化這些問題。使用服務作為組件的另一個后果是更明確的組件接口。大多數語言沒有一個好的機制來定義一個明確的發布接口。通常只有文檔和紀律能夠防止客戶端破壞組件的封裝,導致組件之間過於緊密的耦合。通過使用顯式遠程調用機制,服務可以更容易地避免這種情況。使用這樣的服務確實有缺點。遠程調用比進程內調用更加昂貴,因此遠程API需要更粗粒度,這通常更難以使用。如果您需要更改組件之間的責任分配,那么當您跨越流程邊界時,這種行為的移動難以實現。在第一個近似值中,我們可以觀察到服務映射到運行時進程,但這只是第一個近似值。服務可能由多個進程組成,這些進程將始終開發並部署在一起,例如應用程序進程和僅由該服務使用的數據庫。
圍繞業務能力進行組織
當想要將大型應用程序拆分為多個部分時,管理層往往側重於技術層,導致UI團隊,服務器端邏輯團隊和數據庫團隊協同出現不少問題。當團隊沿着這些路線分開時,即使是簡單的變更也會導致跨團隊項目需要時間和預算批准。一個聰明的團隊將圍繞這一點進行優化,並為兩個弊端中的較小者提供豐富實踐 - 只需將邏輯強制到他們可以訪問的任何應用程序。換言之,就是無處不在的邏輯。這是康威法則一個例子。
任何設計系統(定義廣泛)的組織都將產生一個設計,其結構是該組織通信結構的副本。
- 梅爾文康威,1967年
微服務團隊成員組織的方法不同,分解成圍繞業務能力進行組織的服務 。這些服務需要對該業務領域的軟件進行廣泛的實施,包括用戶界面,持久性存儲和任何外部協作。因此,團隊是跨職能的,包括開發所需的全部技能:用戶體驗,數據庫和項目管理。
是產品不是項目
我們看到的大多數應用程序開發工作都使用項目模型:目標是提供一些隨后被認為已完成的軟件。完成后,軟件被移交給維護組織,並且構建它的項目團隊被解散。微服務支持者傾向於避免這種模式,而更傾向於認為團隊應該在其整個生命周期內擁有產品。對此的一個共同啟發就是亞馬遜的“你自己構建,運行它”的概念,即開發團隊負責生產軟件的全部責任。這使開發人員日常接觸到他們的軟件在生產中的行為,並增加與用戶的聯系,因為他們必須承擔至少一些支持負擔。產品的心態,與企業能力的關聯。軟件並不是一組待完成的功能,而是一個持續的關系,問題是軟件如何幫助其用戶提高業務能力。沒有理由不能為單一應用程序采用同樣的方法,但較小的服務粒度可以更容易地創建服務開發人員與其用戶之間的個人關系。
智能端點和啞管道
在構建不同流程之間的溝通結構時,我們看到許多產品和方法都強調將重要的智慧融入溝通機制本身。一個很好的例子就是企業服務總線(ESB),ESB產品通常包含用於消息路由,編排,轉換和應用業務規則的復雜設施。
成為網絡,而不是網絡后面
- 伊恩羅賓遜
微服務團隊使用萬維網(在很大程度上,Unix)構建的原則和協議。開發人員或操作人員可以通過很少的努力來緩存經常使用的資源。常用的第二種方法是通過輕量級消息總線進行消息傳遞。所選擇的基礎架構通常是愚蠢的(僅僅是作為一個消息路由器的行為) - 簡單的實現,比如RabbitMQ或ZeroMQ,不僅僅是提供可靠的異步結構 - 智能仍然存在於正在生成和消費信息; 在服務中。在整體架構中,組件正在執行中,它們之間的通信通過方法調用或函數調用進行。將巨人變成微服務的最大問題在於改變溝通模式。從內存中方法調用到RPC的天真轉換會導致性能不佳的健談通信。相反,你需要用更粗糙的方法來替換細粒度的通信。
分散治理
集中治理的后果之一是在單一技術平台上實現標准化的趨勢。經驗表明,這種方法是狹隘的 - 並非每一個問題都是釘子,而不是每一個解決方案。我們更喜歡使用正確的工具來完成這項工作,而單片應用程序可以在一定程度上利用不同的語言,但這並不常見。將整體零件拆分成服務時,我們在構建每個服務時都有選擇。你想使用Node.js來站立一個簡單的報告頁面?去吧。C ++用於特別粗糙的近實時組件?精細。你想交換一個不同的數據庫風格,更適合一個組件的讀取行為?我們有技術來重建他。當然,僅僅因為你可以做點什么,並不意味着你應該這樣做- 但是用這種方式划分你的系統意味着你可以選擇。構建微服務的團隊也更喜歡采用不同的標准方法。他們更喜歡生產有用的工具,而其他開發人員可以用它來解決他們所面臨的類似問題,而不是使用一套定義好的標准。這些工具通常從實施中收獲,並與更廣泛的群體共享,有時但不完全使用內部開源模型。
分散數據管理
數據管理的分權化以多種不同的方式呈現。在最抽象的層面上,這意味着世界的概念模型在不同系統之間會有所不同。在整個大型企業中進行整合時,這是一個常見問題,客戶的銷售視圖將與支持視圖不同。在銷售視圖中稱為客戶的某些內容在支持視圖中可能完全不顯示。那些確實可能具有不同的屬性和(更糟糕的)具有微妙不同語義的共同屬性。
以這種方式選擇管理不一致對於許多開發團隊來說是一個新的挑戰,但它往往符合商業慣例。通常企業處理一定程度的不一致性,以便快速響應需求,同時采取某種逆轉過程來處理錯誤。只要修正錯誤的成本低於失敗業務的成本,這種折中是值得的。
基礎設施自動
基礎設施自動化技術在過去幾年中發生了巨大變化 - 特別是雲和AWS的發展降低了構建,部署和運行微服務的運營復雜性。由微服務構建的許多產品或系統都由具有持續交付豐富經驗的團隊構建,這是持續集成的先驅。這種構建軟件的團隊廣泛使用基礎設施自動化技術。由於這不是一篇關於持續交付的文章,我們將在這里提請注意幾個關鍵功能。我們希望盡可能多的信心使我們的軟件能夠工作,所以我們進行了大量的自動化測試。推動工作軟件“向上”流水線意味着我們可以自動部署 到每個新環境。
我們看到團隊使用廣泛的基礎設施自動化的另一個領域是管理生產中的微服務。與我們之前的斷言相反,只要部署無聊,整體架構和微服務之間沒有太大差別,每個架構的運營環境可能會有驚人的不同。
設計失敗
將服務用作組件的后果是應用程序需要進行設計,以便它們可以容忍服務的失敗。任何服務電話都可能由於供應商不可用而失敗,客戶必須盡可能優雅地回應。與單片設計相比,這是一個缺點,因為它引入了額外的復雜性來處理它。結果是微服務團隊不斷反思服務失敗如何影響用戶體驗。
進化設計
微服務從業者通常來自進化設計背景,並將服務分解視為進一步的工具,以使應用程序開發人員能夠控制其應用程序中的更改,而不會降低更改速度。變更控制並不一定意味着降低變更 - 通過正確的態度和工具,您可以對軟件進行頻繁,快速且控制良好的變更。無論您何時試圖將軟件系統分解為組件,您都面臨着如何分割這些組件的決定 - 我們決定切割應用程序的原則是什么?組件的關鍵屬性是獨立替換和可升級性的概念 - 這意味着我們尋找可以想象重寫組件而不影響其協作者的點。事實上許多微服務集團都明確預計許多服務將被廢棄,而不是長遠發展。使用單體應用時,任何更改都需要完整構建和部署整個應用程序。但是,對於微服務,您只需重新部署您修改的服務。這可以簡化並加速發布過程。缺點是你不得不擔心改變一個服務打破它的消費者。傳統的集成方法是嘗試使用版本控制來解決這個問題,但微服務領域的偏好是僅使用版本控制作為最后的手段。我們可以通過設計服務盡可能容忍供應商的變化來避免大量的版本控制。
