Martin Fowler關於微服務的原文翻譯

原文如下:http://martinfowler.com/articles/microservices.html

微服務

一個新的架構術語

“微服務架構”一詞是在過去幾年裏涌現出來的,它用於描述一種獨立部署的軟件應用設計方式。這種架構方式並沒有非常明確的定義,但有一些共同的特點就是圍繞在業務能力、自動化佈署、端到端的整合以及語言和數據的分散控制上面。

“微服務”- 這是在軟件架構領域這個非常擁擠的街道上,冒出的一個新名詞而已。雖然我們對這個新出的名詞不屑一顧,但是它所描述的軟件系統的風格越來越吸引我們的注意力。在過去的幾年裏,我們發現越來越多的項目開始使用這個風格,並且到目前爲止得到的反饋都是積極的,以至於我身邊的許多同事在設計企業架構時,都把它作爲默認的構建方式,然而很不幸,到底什麼是微服務,我們又如何來使用它,外界並沒有太多的信息可供參考。

總之,微服務這種架構風格就是把一組小服務演化成爲一個單一的應用的一種方法。每個應用都運行在自己的進程中,並通過輕量級的機制保持通信,就像HTTP這樣的API。這些服務要基於業務場景,並使用自動化佈署工具進行獨立的發佈。可以有一個非常輕量級的集中式管理來協調這些服務,可以使用不同的語言來編寫服務,也可以使用不同的數據存儲。

在開始解釋什麼是微服務之前,先介紹一下單體應用還是很有用的:把一個單體應用構建成爲一個部分。企業應用通過是由三個重要部分組成:客戶端界面(由HTML、Javascript組成,使用瀏覽器進行訪問)、數據庫(由許多的表組件構成一個通用的、相互關聯的數據管理系統)、服務端應用。服務端應用處理HTTP請求、執行領域邏輯、檢索並更新數據庫中的數據、選擇和填充HTML視圖發送給客戶端。這個服務端應用是一個單塊結構也就是一個整體,這是一個可執行的單一邏輯,系統中的任何修改都將導致服務端應用重新編譯和佈署一個新版本。

就這樣一個單體應用很自然的被構建成了一個系統,雖然可以使用開發語言基本特性會把應用封裝成類、函數、命名空間,但是業務中所有請求都要在單一的進程中處理完成,在某些場景中,你可以在開發人員的筆記本電腦中運行和測試,並且通過佈署通道將測試通過的程序佈署到生產環境中,你還可以水平擴展,利用負載均衡將實例佈署到多臺服務器中。

的確,單體應用也是很成功的,但是越來越多的人感覺到了不妥,特別是應用程序被髮布到了雲的時候,變更發佈週期被綁定了 —- 原來可以劃分成小的應用、小的需要的變更,需要統一的進行編譯和發佈。隨着時間的推移,軟件開發者很難保持原有好的模塊架構,使得一個模塊的變更很難不會影響到其它的模塊,而且在擴展方面也只能進行整體的擴展,而不能根據進行部分的擴展。 
這裏寫圖片描述

這些原因導致了微服務架構風格的出現:以服務構建應用。這些服務還可以被獨立佈署、獨立擴展,每個服務也都提供了清晰的模塊邊界,甚至不同的服務都可以使用不同的編程語言來實現,也可以由不同的團隊進行管理。

微服務的概念不是我們發明的,它至少起源於Unix時代的設計原則,我們認爲這種風格所帶來的好處,並沒有引起足夠多人的重視。

微服務架構特徵

我們沒有辦法對微服務有一個正式的定義,但我們可以嘗試表述適合這種架構的共同特徵來給它打上特性標籤,共同特性並不代表每個服務都具備這些特點,但是我們真的期望大多數微服務架構能具備其中大部分特點。雖然我們的作者已經是鬆散社區的核心成員,但是我們也在嘗試描述我們工作中或者我們瞭解的組件中所理解的微服務。我們並不依賴於那些已經明確過的定義。

組件化與服務

只要我們一直在從事軟件行業,我們的願望就是,軟件由很多組件組裝在一起,如同物理現實世界中類似的構造方式。在過去的幾十年裏,我們已經看到了大部分語言平臺公共庫有了長足的進步。

當我們在談論組件時,我們遇到了組件定義方面的困難,我們給定的定義是:一個組件是軟件中的一個部分,可以獨立的替換和升級。

微服務也會使用組件庫,將一個軟件組件化的主要方式就是將其分解成服務,我們定義的庫是可以連接到程序並使用內存函數的的組件庫,服務是進程外的組件,如Web請求服務或者遠程調用來相互通信的組件。(這種定義的方式與其它面向對象程序中服務對象的概念是不一樣的。)

把服務當成組件(而不是組件庫)的一個原因是服務可以獨立佈署,如果你有一個應用是由多個庫組成並且運行在一個進程中,那麼任何一點的改變都會引起整個應用的重新發布,但是將這個應用拆解爲多個服務,你可以期待每個服務的變更僅需要發佈相應的服務就可以,當然這也不是絕對的,比如導致服務接口變更的更新就需要相應服務的變化,但是良好的架構設計是通過聚合服務邊界並且按照合約實現服務演化,最大限度地減少因爲改變影響其他地方。

把服務當成組件的另一個考慮是這會擁有更加清晰的接口,大多數的語言並沒有一個很好的機制來定義一個明確顯式的發佈接口,通常只有文檔和規範說明,讓用戶避免組件間過度緊密而導致高耦合,通過顯示的遠程調用機制,可以避免這種情況。

使用服務也有其自身的缺點,遠程調用比進程內部調用更加消耗性能,而且遠程的API往往是粗粒度的,用起來不是很友好,對組件的職責進行變更,也會影響到進程間的交互,那麼操作起來也比較困難。

第一個可能性,我們看到每個服務是運行在獨立的進程上的。注意,這只是第一個可能性。服務也可以由多個進程組成,它們是同時開發和部署的,如果一個應用進程和一個僅由該服務使用的數據庫。

圍繞業務能力進行組織

當我們把一個大的應用拆分成小的部分時,我們的注意力主要集中在技術層面,拆分成UI團隊、服務端的邏輯團隊和數據庫團隊。當使用這種標準對團隊進行劃分時,甚至一個非常小的更變都將導致跨團隊間項目協作,從而消耗時間和預算審批。一個高效的團隊會針對這種情況進行改善,關注它們所涉及的應用邏輯,並從中做出較好的選擇。換句話說,邏輯無處不在。康威定律就是一個例子。

一個組織的溝通結構反映了其設計的系統的結構

-- Melvyn Conway, 1967
  • 1
  • 2
  • 3

這裏寫圖片描述

微服務的劃分方法有所不同,它更傾向於圍繞業務功能對服務結構進行劃分、拆解,這些服務可以採用不同的技術棧來實現,包括用戶界面,持久層存儲,或任何對外協作,因此團隊應該是跨職能的,包括開發所需要的全部技術:用戶體驗、數據庫和項目管理。

這裏寫圖片描述

按照這種方式組織的公司是 www.comparethemarket.com,跨職能團隊負責建立和操作每個產品並且每個產品都被分成若干單獨的服務通過消息進行通信。

大型的單體應用也可以按照業務功能進行模塊化的,儘管這種例子不常見。當然,我們也會敦促一個大型團隊在構建一個單體應用時按照業務線來進行劃分,我們能看到主要問題在於,這種組件形式會導致很多的上下文依賴,如果這個系統跨越很多模塊邊界,對於一個單獨團隊是很難在短時間解決問題的。此外,我們發現模塊化方式需要大量的規範去強制執行,而服務組件明確的劃分,使得團隊間的邊界也變得清晰起來。

產品不是項目

大多數的開發工作是使用這樣一種模型:其目的是完成可以交付的軟件,軟件開發完成就交給了維護團隊,該項目組也就解散了。

微服務的支持者建議避免這種模型,認爲一個團隊應該負責產品的整個生命週期,一個很通用的概念就是Amazon’s的“you build, you run it”,它要求開發團隊對軟件產品的整個生命週期負責,這使得開發人員可以每天都關注產品的運行情況,而且也能夠與用戶保持緊密的聯繫,做一些必要的支持工作。

產品方式開發意味着與業務能力緊緊捆綁在一起,而不是將軟件看成是一系列完成的功能,他們會關注如何讓軟件幫助其用戶提升業務能力。

單體應用也可以採用上述產品的理念,但是更小粒度的服務可以更容易的創建開發者與用戶之間的關係。

智能終端與弱管道

當在不同的進程之間構建各種通信結構時,我們已經看到許多產品和方法,來強調將大量的智能特性融入到通信機制本身,這種情況的一個典型例子就是“企業服務總線”(Enterprise Service Bus,ESB)。ESB產品經常包括高度智能的設施來進行消息的路由、編排、轉換,並應用業務規則。

微服務社區主張採用另一種做法:智能終端和弱管道。使用微服務所構建的各個應用的目標都是儘可能實現“高內聚和低耦合”–他們擁有自己的領域邏輯,並且更多的是經典的UNIX的“過濾器”那樣工作–即接收請求、處理邏輯、返回響應,這些應用通過使用簡單的REST風格的協議來進行編排,而不去使用複雜的協議,比如:WS、BEPL或者集中式工具進行編排。

有兩種協議最經常被使用到:包含資源API的HTTP的請求-響應和輕量級消息通信協議。最爲重要的建議爲:

微服務團隊採用這樣的原則和規範:基於互聯網(廣義上,包含Unix系統)構建系統。這樣經常使用的資源幾乎不用什麼的代價就可以被開發者或者運行商緩存。

第二種做法是通過輕量級消息總線來發布消息。這種的通信協議非常的單一(單一到只負責消息路由),像RabbitMQ或者ZeroMQ這樣的簡單的實現甚至像可靠的異步機制都沒提供,以至於需要依賴產生或者消費消息的終端或者服務來處理這類問題。

在一個單塊系統中,各個組件在同一個進程中運行。它們相互之間的通信,要麼通過方法調用,要麼通過函數調用來進行。將一個單塊系統改造爲若干微服務的最大問題,在於對通信模式的改變。僅僅將內存中的方法調用轉換爲RPC調用這樣天真的做法,會導致微服務之間產生繁瑣的通信,使得系統表現變糟。取而代之的是,需要用更粗粒度的協議來替代細粒度的服務間通信。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章