[譯]微服務-Martin Fowler(轉)

做者:YYGCuigit

出處:http://blog.cuicc.com/blog/2015/07/22/microservices/github

 

在過去幾年中,「微服務架構」這一術語如雨後春筍般涌現出來,它描述了一種將軟件應用程序設計爲一組可獨立部署的服務的特定方式。雖然這種架構風格沒有明確的定義,但在組織、業務能力上有一些共同的特徵:自動化部署,端點智能化,語言和數據的去中心化控制。web

 

「微服務」 - 軟件架構擁擠大街上的有一個新術語。雖然咱們天然的傾向是輕蔑的一瞥將它一帶而過,然而咱們發現這一術語描述了一種愈來愈吸引人的軟件系統風格。咱們已看到,在過去的幾年中有許多項目使用了這種風格,而且到目前爲止結果都還不錯,以至於這已變成了咱們同事在構建企業級應用程序時默認使用的架構風格。然而,遺憾的是並無太多的信息來概述什麼是微服務風格以及怎樣用這種風格。數據庫

簡單來講,微服務架構風格[1]是一種將一個單一應用程序開發爲一組小型服務的方法,每一個服務運行在本身的進程中,服務間通訊採用輕量級通訊機制(一般用HTTP資源API)。這些服務圍繞業務能力構建而且可經過全自動部署機制獨立部署。這些服務共用一個最小型的集中式的管理,服務可用不一樣的語言開發,使用不一樣的數據存儲技術。編程

與單體風格做對比有助於開始解釋微服務風格:單體應用程序被構建爲單一單元。企業級應用程序一般由三部分組成:客戶端側用戶接口(由運行於開發機上的瀏覽器裏的HTML頁面和Javascript組成),數據庫(由插入到通用關係型數據庫管理系統中的許多數據表格組成),服務端應用程序。服務端應用程序處理HTTP請求,執行領域邏輯,從數據庫中檢索、更新數據,選擇、填充將要發送到瀏覽器的HTTP視圖。服務端應用程序是一個單一的邏輯可執行單體[2]。系統的任何改變都將牽涉到從新構建和部署服務端的一個新版本。瀏覽器

這樣的單體服務器是構建這樣一個系統最天然的方式。處理請求的全部邏輯都運行在一個單一進程中,容許你使用編程語言的基本特性將應用程序劃分類、函數和命名空間。你認真的在開發機上運行測試應用程序,並使用部署管道來保證變動已被正確地測試並部署到生產環境中。該單體的水平擴展能夠經過在負載均衡器後面運行多個實例來實現。緩存

單體應用程序能夠是成功的,但人們日益對他們感到挫敗,尤爲是隨着更多的應用程序被部署在雲上。變動週期被捆綁在一塊兒 —— 即便只變動應用程序的一部分,也須要從新構建並部署整個單體。久而久之,一般將很難保持一個良好的模塊架構,這使得很難變動只發生在須要變動的模塊內。程序擴展要求進行整個應用程序的擴展而不是須要更多資源的應用程序部分的擴展。性能優化

 

圖1: 單體和微服務服務器

這些挫敗導向了微服務架構風格:構建應用程序爲服務套件。除了服務是可獨立部署、可獨立擴展的以外,每一個服務都提供一個固定的模塊邊界。甚至容許不一樣的服務用不一樣的的語言開發,由不一樣的團隊管理。網絡

咱們不會聲稱微服務風格是新穎的、創新的,其本質至少能夠回溯到Unix的設計哲學。但咱們的確認爲沒有足夠的人仔細考慮微服務架構,而且若是使用它不少軟件實現將會更好。

微服務架構的特徵

咱們沒法給出微服務架構風格的一個正式定義,但咱們能夠嘗試去描述咱們看到的符合該架構的一些共性。就概述共性的任何定義來講,並不是全部的微服務架構風格都有這些共性,但咱們指望大多數微服務架構風格展示出大多數特性。雖然本文做者一直是這個至關鬆散的社區的活躍用戶,咱們的目的是試圖描述咱們工做中和咱們知道的一些團隊的類似努力中的所見所聞。特別是咱們不會制定一些可遵照的定義。

經過服務組件化

只要咱們一直從事軟件行業,一個願望就是經過把組件插在一塊兒構建系統,如同咱們看到的現實世界中事物的構造方式同樣。在最近的二十年中,咱們看到做爲大多數語言平臺一部分的公共庫的大量彙編工做取得了很大的進展。

當談到組件時,咱們遭遇困難的定義:組件是什麼。咱們的定義是:組件是一個可獨立替換和獨立升級的軟件單元。

微服務架構將使用庫,但組件化軟件的主要方式是分解成服務。咱們把庫定義爲連接到程序並使用內存函數調用來調用的組件,而服務是一種進程外的組件,它經過web服務請求或rpc(遠程過程調用)機制通訊(這和不少面向對象程序中的服務對象的概念是不一樣的[3]。)

使用服務做爲組件而不是使用庫的一個主要緣由是服務是可獨立部署的。若是你有一個應用程序[4]是由單一進程裏的多個庫組成,任何一個組件的更改都致使必須從新部署整個應用程序。但若是應用程序可分解成多個服務,那麼單個服務的變動只須要從新部署該服務便可。固然這也不是絕對的,一些變動將會改變服務接口致使一些協做,但一個好的微服務架構的目的是經過內聚服務邊界和按合約演進機制來最小化這些協做。

使用服務做爲組件的另外一個結果是一個更加明確的組件接口。大多數語言沒有一個好的機制來定義一個明確的發佈接口。一般只有文檔和規則來預防客戶端打破組件的封裝,這致使組件間過於緊耦合。服務經過明確的遠程調用機制能夠很容易的避免這些。

像這樣使用服務確實有一些缺點,遠程調用比進程內調用更昂貴,所以遠程API被設計成粗粒度,這每每更不便於使用。若是你須要更改組件間的責任分配,當你跨進程邊界時,這樣的行爲動做更難達成。

直觀的估計,咱們觀察到服務與運行時進程一一映射,但這僅僅是直觀的估計而已。一個服務可能由多進程組成,這些進程老是被一塊兒開發和部署,好比只被這個服務使用的應用進程和數據庫。

圍繞業務能力組織

當想要把大型應用程序拆分紅部件時,一般管理層聚焦在技術層面,致使UI團隊、服務側邏輯團隊、數據庫團隊的劃分。當團隊按這些技術線路劃分時,即便是簡單的更改也會致使跨團隊的時間和預算審批。一個聰明的團隊將圍繞這些優化,兩害取其輕 - 只把業務邏輯強制放在它們會訪問的應用程序中。換句話說,邏輯無處不在。這是Conway法則[5]在起做用的一個例子。

任何設計系統(普遍定義的)的組織將產生一種設計,他的結構就是該組織的通訊結構。

-- Melvyn Conway 1967

 

圖2: Conway法則在起做用

微服務採用不一樣的分割方法,劃分紅圍繞業務能力組織的服務。這些服務採起該業務領域軟件的寬棧實現,包括用戶接口、持久化存儲和任何外部協做。所以,團隊都是跨職能的,包括開發須要的全方位技能:用戶體驗、數據庫、項目管理。

 

圖3: 團隊邊界加強的服務邊界

www.comparethemarket.com是按這種方式組織的一個公司。跨職能團隊負責建立和運營產品,產品被劃分紅若干個體服務,這些服務經過消息總線通訊。

大型單體應用程序也老是能夠圍繞業務能力來模塊化,雖然這不是常見的狀況。固然,咱們將敦促建立單體應用程序的大型團隊將團隊自己按業務線拆分。咱們看到這種狀況的主要問題是他們趨向於圍繞太多的上下文進行組織。若是單體橫跨了多個模塊邊界,對團隊個體成員來講,很難把它們裝進他們的短時間記憶裏。另外,咱們看到模塊化的路線須要大量的規則來強制實施。服務組件所要求的更加明確的分離,使得它更容易保持團隊邊界清晰。

側邊欄:微服務有多大?

雖然,「微服務」已成爲這種架構風格的代稱,這個名字確實會致使不幸的聚焦於服務的大小,併爲「微」由什麼組成爭論不休。在與微服務實踐者的對話中,咱們發現有各類大小的服務。最大的服務報道遵循亞馬遜兩匹薩團隊(也就是,整個團隊吃兩個披薩就吃飽了)的理念,這意味着團隊不超過12我的。在更小的規模大小上,咱們看到這樣的安排,6人團隊將支持6個服務。

這致使這樣一個問題,在服務每12我的和服務每1我的的大小範圍內,是否有足夠打的不一樣使他們不能被集中在同一微服務標籤下。目前,咱們認爲最好把它們組合在一塊兒。但隨着深刻探索這種風格,咱們必定有可能改變咱們的見解。

是產品不是項目

咱們看到大多數應用程序開發工做使用一個項目模式:目標是交付將要完成的一些軟件。完成後的軟件被交接給維護組織,而後它的構建團隊就解散了。

微服務支持者傾向於避免這種模式,而是認爲一個團隊應該負責產品的整個生命週期。對此一個共同的啓示是亞馬遜的理念 「you build, you run it」 ,開發團隊負責軟件的整個產品週期。這使開發者常常接觸他們的軟件在生產環境如何工做,並增長與他們的用戶聯繫,由於他們必須承擔至少部分的支持工做。

產品思想與業務能力牢牢聯繫在一塊兒。要持續關注軟件如何幫助用戶提高業務能力,而不是把軟件當作是將要完成的一組功能。

沒有理由說爲何一樣的方法不能用在單體應用程序上,但服務的粒度更小,使得它更容易在服務開發者和用戶之間創建我的關係。

智能端點和啞管道

當在不一樣進程間建立通訊結構時,咱們已經看到了不少的產品和方法,把顯著的智慧強壓進通訊機制自己。一個很好的例子就是企業服務總線(ESB),在ESB產品中一般爲消息路由、編排(choreography)、轉化和應用業務規則引入先進的設施。

微服務社區主張另外一種方法:智能端點和啞管道。基於微服務構建的應用程序的目標是儘量的解耦和儘量的內聚 - 他們擁有本身的領域邏輯,他們的行爲更像經典UNIX理念中的過濾器 - 接收請求,應用適當的邏輯併產生響應。使用簡單的REST風格的協議來編排他們,而不是使用像WS-Choreography或者BPEL或者經過中心工具編制(orchestration)等複雜的協議。

最經常使用的兩種協議是使用資源API的HTTP請求-響應和輕量級消息傳送[6]。對第一種協議最好的表述是

自己就是web,而不是隱藏在web的後面。

-- Ian Robinson

微服務團隊使用的規則和協議,正是構建萬維網的規則和協議(在更大程度上,是UNIX的)。從開發者和運營人員的角度講,一般使用的資源能夠很容易的緩存。

第二種經常使用方法是在輕量級消息總線上傳遞消息。選擇的基礎設施是典型的啞的(啞在這裏只充當消息路由器) - 像RabbitMQ或ZeroMQ這樣簡單的實現僅僅提供一個可靠的異步交換結構 - 在服務裏,智能仍舊存活於端點中,生產和消費消息。

單體應用中,組件都在同一進程內執行,它們之間經過方法調用或函數調用通訊。把單體變成微服務最大的問題在於通訊模式的改變。一種幼稚的轉換是從內存方法調用轉變成RPC,這致使頻繁通訊且性能很差。相反,你須要用粗粒度通訊代替細粒度通訊。

去中心化治理

集中治理的一個後果是單一技術平臺的標準化發展趨勢。經驗代表,這種方法正在收縮 - 不是每一個問題都是釘子,不是每一個問題都是錘子。咱們更喜歡使用正確的工具來完成工做,而單體應用程序在必定程度上能夠利用語言的優點,這是不常見的。

把單體的組件分裂成服務,在構建這些服務時能夠有本身的選擇。你想使用Node.js開發一個簡單的報告頁面?去吧。用C++實現一個特別粗糙的近乎實時的組件?好極了。你想換用一個更適合組件讀操做數據的不一樣風格的數據庫?咱們有技術來重建它。

固然,僅僅由於你能夠作些什麼,而不意味着你應該這樣作 - 但用這種方式劃分系統意味着你能夠選擇。

團隊在構建微服務時也更喜歡用不一樣的方法來達標。他們更喜歡生產有用的工具這種想法,而不是寫在紙上的標準,這樣其餘開發者能夠用這些工具解決他們所面臨的類似的問題。有時,這些工具一般在實施中收穫並與更普遍的羣體共享,但不徹底使用一個內部開源模型。如今git和github已經成爲事實上的版本控制系統的選擇,在內部開放源代碼的實踐也正變得愈來愈常見。

側邊欄:微服務和SOA

當咱們談論微服務時,一個常見問題是它是否僅僅是十年前咱們看到的面向服務的架構(SOA)。這一點是有可取之處的,由於微服務風格和SOA贊同的某些主張十分類似。然而,問題是SOA意味着不少不一樣的東西,而大多數時候,咱們遇到的所謂的SOA和這裏咱們描述的風格明顯不一樣,這種不一樣一般因爲SOA專一於用於集成單體應用的ESB。

特別是咱們已看到太多的搞砸的服務導向的實現,從趨向於隱藏ESB中的複雜性[7],到花費數百萬並不產生任何價值的失敗的多年舉措,到積極抑制變化的集中治理模型,這有時很難看到過去的這些問題。

固然,微服務社區用到的許多技術從開發者在大型組織機構整合服務的經驗中成長。Tolerant Reader模式就是這樣的一個例子。使用簡單協議是衍生自這些經驗的另外一個方法,使用網絡的努力已作出遠離中央標準的反應,坦率地說,中心標準已達到使人歎爲觀止的複雜性。(任什麼時候候,你須要一個本體來管理你的本體,你知道你深陷困境。)

SOA的這種常見表現使得一些微服務倡導者徹底拒絕SOA標籤,儘管其餘人認爲微服務時SOA的一種形式[8],也許服務導向作得對。不管哪一種方式,事實上,SOA意味着如此不一樣的事情,這意味着有一個術語來更清晰地定義這種架構風格是有價值的。

Netflix是遵照這一理念的很好的例子。尤爲是,以庫的形式分享有用的且通過市場檢驗的代碼,這激勵其餘開發者用相似的方式解決類似的問題,同時還爲採用不一樣方法敞開了大門。共享庫傾向於聚焦在數據存儲、進程間通訊和咱們接下來要深刻討論的基礎設施自動化的共性問題。

對爲服務社區來講,開銷特別缺少吸引力。這並非說社區不重視服務合約。偏偏相反,由於他們有更多的合約。只是他們正在尋找不一樣的方式來管理這些合約。像Tolerant Reader和消費者驅動的契約(Consumer-Driven Contracts)這樣的模式一般被用於微服務。
這些援助服務合約在獨立進化。執行消費者驅動的合約做爲構建的一部分,增長了信心並對服務是否在運做提供了更快的反饋。事實上,咱們知道澳大利亞的一個團隊用消費者驅動的合約這種模式來驅動新業務的構建。他們使用簡單的工具定義服務的合約。這已變成自動構建的一部分,即便新服務的代碼還沒寫。服務僅在知足合約的時候才被建立出來 - 這是在構建新軟件時避免"YAGNI"[9]困境的一個優雅的方法。圍繞這些成長起來的技術和工具,經過減小服務間的臨時耦合,限制了中心合約管理的須要。

側邊欄:許多語言,許多選項

JVM做爲平臺的成長就是在一個共同平臺內混合語言的最新例子。幾十年來,破殼到高級語言利用高層次抽象的優點已成爲一種廣泛的作法。如同下拉到機器硬件,用低層次語言寫性能敏感的代碼同樣。然而,不少單體不須要這個級別的性能優化和常見的更高層次的抽象,也不是DSL的。相反,單體一般是單一語言的並趨向於限制使用的技術的數量[10]。

也許去中心化治理的最高境界就是亞馬遜廣爲流傳的build it/run it理念。團隊要對他們構建的軟件的各方面負責,包括7*24小時的運營。這一級別的責任下放絕對是不規範的,但咱們看到愈來愈多的公司讓開發團隊負起更多責任。Netflix是採用這一理念的另外一家公司[11]。天天凌晨3點被傳呼機叫醒無疑是一個強有力的激勵,使你在寫代碼時關注質量。這是關於儘量遠離傳統的集中治理模式的一些想法。

去中心化數據管理

數據管理的去中心化有許多不一樣的呈現方式。在最抽象的層面上,這意味着使系統間存在差別的世界概念模型。在整合一個大型企業時,客戶的銷售視圖將不一樣於支持視圖,這是一個常見的問題。客戶的銷售視圖中的一些事情可能不會出如今支持視圖中。它們確實可能有不一樣的屬性和(更壞的)共同屬性,這些共同屬性在語義上有微妙的不一樣。

這個問題常見於應用程序之間,但也可能發生在應用程序內部,尤爲當應用程序被劃分紅分離的組件時。一個有用的思惟方式是有界上下文(Bounded Context)內的領域驅動設計(Domain-Driven Design, DDD)理念。DDD把一個複雜域劃分紅多個有界的上下文,而且映射出它們之間的關係。這個過程對單體架構和微服務架構都是有用的,但在服務和上下文邊界間有自然的相關性,邊界有助於澄清和增強分離,就像業務能力部分描述的那樣。

側邊欄:久經考驗的標準和執行標準

這有一點分裂,微服務團隊傾向於避開企業架構組規定的那種嚴格的執行標準,但又很樂意使用甚至傳教開放標準,好比HTTP、ATOM和其餘威格士。

關鍵的區別是如何定製標準和如何執行。由諸如IETF等組織管理的標準僅當在世界範圍內有幾個有用的實現時才變成標準,這每每會從成功的開源項目成長起來。

這些標準是遠離企業世界的標準。每每被一個幾乎沒有近期編程經驗的或受供應商過分影響的組織開發的。

和概念模型的去中心化決策同樣,微服務也去中心化數據存儲決策。雖然單體應用程序更喜歡單一的邏輯數據庫作持久化存儲,但企業每每傾向於一系列應用程序共用一個單一的數據庫 - 這些決定是供應商受權許可的商業模式驅動的。微服務更傾向於讓每一個服務管理本身的數據庫,或者同一數據庫技術的不一樣實例,或徹底不一樣的數據庫系統 - 這就是所謂的混合持久化(Polyglot Persistence)。你能夠在單體應用程序中使用混合持久化,但它更常出如今爲服務裏。

對跨微服務的數據來講,去中心化責任對管理升級有影響。處理更新的經常使用方法是在更新多個資源時使用事務來保證一致性。這個方法一般用在單體中。

像這樣使用事務有助於一致性,但會產生顯著地臨時耦合,這在橫跨多個服務時是有問題的。分佈式事務是出了名的難以實現,所以微服務架構強調服務間的無事務協做,對一致性可能只是最後一致性和經過補償操做處理問題有明確的認知。

對不少開發團隊來講,選擇用這樣的方式管理不一致性是一個新的挑戰,但這一般與業務實踐相匹配。一般業務處理必定程度的不一致,以快速響應需求,同時有某些類型的逆轉過程來處理錯誤。這種權衡是值得的,只要修復錯誤的代價小於更大一致性下損失業務的代價。

基礎設施自動化

在過去的幾年中,基礎設施自動化已經發生了巨大的變化,特別是雲和AWS的演化已經下降了構建、部署和運維微服務的操做複雜度。

許多用微服務構建的產品或系統是由在持續部署和它的前身持續集成有豐富經驗的團隊構建的。團隊用這種方式構建軟件,普遍使用了基礎設施自動化。以下面的構建管線圖所示:

圖5: 基礎構建管道

由於這不是一篇關於持續交付的文章,咱們這裏將之光住幾個關鍵特性。咱們但願有儘量多的信心,咱們的軟件正在工做,因此咱們運行大量的自動化測試。促進科工做軟件沿管道線「向上」意味着咱們自動化部署到每一個新的環境中。

一個單體應用程序能夠十分愉快地經過這些環境被構建、測試和推送。事實證實,一旦你爲單體投入了自動化生產之路,那麼部署更多的應用程序彷佛也不會更可怕。請記住,持續部署的目標之一是使部署枯燥,因此不管是一個或三個應用程序,只要它的部署仍然枯燥就不要緊[12]。

側邊欄:使它容易作正確的事情

咱們發現,做爲持續交付和持續部署的一個後果,增長自動化的一個反作用是創造有用的工具,以幫助開發人員和運營人員。用於創造人工製品、管理代碼庫、起立(standing up)簡單服務或添加標準監控和日誌記錄的工具如今都是很常見的。web上最好的例子多是Netflix的開源工具集,但也有其餘咱們普遍使用的工具,如Dropwizard。

咱們看到團隊使用大量的基礎設施自動化的另外一個領域是在生產環境中管理微服務時。與咱們上面的斷言(只要部署是枯燥的)相比,單體和微服務沒有太大的差異,各運營場景能夠明顯不一樣。

圖6: 模塊部署經常不一樣

爲失效設計

使用服務做爲組件的一個結果是,應用程序須要被設計成可以容忍服務失效。任何服務調用均可能由於供應者不可用而失敗,客戶端必須儘量優雅的應對這種失敗。與單體應用設計相比這是一個劣勢,由於它引入額外的複雜性來處理它。結果是,微服務團隊不斷反思服務失效如何影響用戶體驗。Netflix的Simian Army在工做日誘導服務甚至是數據中心故障來測試應用程序的彈性和監測。

在生產環境中的這種自動化測試足夠給大多數運營團隊那種毛骨悚然,一般在結束一週的工做以前。這不是說單體風格不可以進行完善的監測設置,只是在咱們的經驗中比較少見。

側邊欄:斷路器和產品就緒代碼

斷路器(Circuit Breaker)與其餘模式如Bulkhead和Timeout出如今《Release it!》中。這些模式是被一塊兒實現的,在構建通訊應用程序時,它們是相當重要的。這篇Netflix博文很好的解釋了使用這些模式的應用程序。

既然服務隨時均可能失敗,那麼可以快速檢測故障,若是可能的話,能自動恢復服務是很重要的。微服務應用程序投入大量比重來進行應用程序的實時監測,既檢查構形要素(每秒多少次數據請求),又檢查業務相關指標(例如每分鐘收到多少訂單)。語義監測能夠提供一套早期預警系統,觸發開發團隊跟進和調查。

這對微服務架構特別重要,由於微服務偏好編排和事件協做,這會帶來突發行爲。雖然不少專家稱讚偶然涌現的價值,事實的真相是,突發行爲有時多是一件壞事請。監測對於快速發現不良突發行爲是相當重要的,因此它能夠被修復。

單體能夠被構建成和微服務同樣透明 - 事實上,它們應該是透明的。不一樣的是,你絕對須要知道在不一樣進程中運行的服務是否斷開。對同一進程中的庫來講,這種透明性是不大可能有用的。

側邊欄:同步調用被認爲是有害的

任什麼時候候,在服務間有大量的同步調用,你將遇到停機的乘法效應。簡單地說,就是你的系統的停機時間編程各個組件停機時間的乘積。你面臨一個選擇,讓你的調用變成異步或者管理停機時間。在www.guardian.co.uk,他們已在新平臺實現了一個簡單的規則 - 每一個用戶請求一個同步調用,而在Netflix,他們的平臺API重設計成在API交換結構(fabric)創建異步性。

微服務團隊但願看到爲每一個單獨的服務設置的完善的監控和日誌記錄,好比控制面板上顯示啓動/關閉狀態和各類各樣的運營和業務相關指標。斷路器狀態、當前吞吐量和時延的詳細信息是咱們常常遇到的其餘例子。

進化式設計

微服務從業者,一般有進化式設計背景而且把服務分解看作是進一步的工具,使應用程序開發者可以控制他們應用程序中的變動而不減緩變動。變動控制並不必定意味着變動的減小 - 用正確的態度和工具,你能夠頻繁、快速且控制良好的改變軟件。

當你試圖把軟件系統組件化時,你就面臨着如何劃分紅塊的決策 - 咱們決定分割咱們的應用的原則是什麼?組件的關鍵特性是獨立的更換和升級的理念[13] - 這意味着咱們要找到這樣的點,咱們能夠想象重寫組件而不影響其合做者。事實上不少微服務羣組經過明確地預期許多服務將被廢棄而不是長期演進來進一步找到這些點。

衛報網站是被設計和構建成單體應用程序的一個好例子,但它已向微服務方向演化。網站的核心還是單體,但他們喜歡經過使用調用單體API構建的微服務添加新功能。這種方法對自然臨時性的特性特別方便,好比處理體育賽事的專題頁面。網站的這樣一部分可使用快速開發語言迅速的被放在一塊兒,而且一旦賽事結束當即刪除。在金融機構中,咱們看到相似的方法,爲一個市場機會添加新服務,並在幾個月甚至幾周後丟棄掉。

強調可替代性是模塊設計更通常原則的一個特例,它是經過變動模式來驅動模塊化的[14]。你想保持在同一模塊中相同時間改變的事情。系統中不多變動的部分應該和正在經歷大量擾動的部分放在不一樣的服務裏。若是你發現你本身不斷地一塊兒改變兩個服務,這是它們應該被合併的一個標誌。

把組件放在服務中,爲更細粒度的發佈計劃增長了一個機會。對單體來講,任何變動都須要完整構建和部署整個應用程序。而對微服務來講,你只須要從新部署你修改的服務。這能夠簡化和加速發佈過程。壞處是,你必須擔憂一個服務的變化會阻斷其消費者。傳統的集成方法試圖使用版本管理解決這個問題,可是微服務世界的偏好是隻把版本管理做爲最後的手段。咱們能夠避免大量的版本管理,經過把服務設計成對他們的提供者的變化儘量的寬容。

微服務是將來嗎?

咱們寫這篇文章的主要目的是講解微服務的主要思想和原則。經過花時間作這件事情,咱們清楚地認爲微服務架構風格是一個重要的思想 - 它值得爲企業應用程序認真考慮。咱們最近用這種風格構建了一些系統,也知作別人用這種風格並同意這種風格。

那些咱們知道的以某種方式開拓這種架構風格的包括亞馬遜,Netflix,衛報,英國政府數字服務部門,realestate.com.au,前鋒和comparethemarket.com。2013年的會議電路中全是正向微服務類別轉移的公司 - 包括Travis CI。此外還有大量的組織長期以來一直在作可歸爲微服務類別的事情,可是尚未使用這個名字。(這一般被稱爲SOA - 雖然,正如咱們說過的,SOA有許多矛盾的形式。[15])

儘管有這些積極的經驗,可是,咱們並不認爲咱們確信微服務是軟件架構的將來發展方向。雖然到目前爲止,與單體應用程序相比,咱們的經驗是正面的,但咱們意識到這樣的事實,並無通過足夠的時間使咱們作出充分的判斷。

一般,你的架構決策的真正後果是在你作出這些決定的幾年後才顯現的。咱們已經看到對模塊化有強烈願望的一個好團隊用單體架構構建的項目,已經衰敗了多年。不少人相信微服務是不太可能出現這種衰敗的,由於服務界限是明確的,而且很難圍繞它打補丁。然而,知道咱們看到通過足夠歲月的足夠的系統,咱們不能真正評估微服務架構有多麼成熟。

人們固然有理由但願微服務時多麼不成熟。在組件化中作任何努力,成功取決於軟件在多大程度上適用於組件化。很難弄清楚組件邊界在哪裏。進化式設計認可獲取正確邊界的困難性和使它們易於重構的重要性。但當你的組件是帶有遠程通訊的服務時,那麼重構它比重構帶有進程內庫的服務難不少。跨服務邊界移動代碼是很困難的,任何接口變動都須要在參與者之間進行協調,須要添加向後兼容層,而且測試也變得更加複雜。

側邊欄:《構建微服務》

咱們的同事Sam Newman花費2014年的大部分時間寫了一本書,捕捉了咱們構建微服務的經驗。若是你想深刻到這個話題中,這應該是你的下一步。

另外一個問題是,若是組件不組成的乾淨利索,那麼全部你作的是將複雜度從組件內部轉移到組件之間的鏈接。不只僅是把複雜性移到周圍,它將複雜性移動到一個不太明確、難以控制的地方。在沒有服務間的凌亂鏈接的狀況下,當你在看一個小的、簡單的組件內部時,你能夠很容易的認爲事情是更好的。

最後,有團隊技能的因素。更熟練的團隊傾向於採用新技術。可是對更熟練的團隊更有效的一種技術不必定適合於不太熟練的團隊。咱們已經看到大量的例子,不太熟練的團隊構建了凌亂的單體架構,但這須要時間去看當微服務發生這種凌亂時會發生什麼。一個差的團隊老是建立一個差的系統 - 很難講在這個例子中微服務會減小這種凌亂仍是使它更糟糕。

咱們聽到的一個合理的說法是,你不該該從微服務架構開始。相反,從單體開始,使它保持模塊化,一旦單體成爲問題時把它分解成微服務。(雖然這個建議是不理想的,由於一個好的進程內接口一般不是一個好的服務接口。)

因此咱們懷着謹慎樂觀的態度寫了這篇文章。到目前爲止,咱們已經看到關於微服務風格足以以爲這是一條值得探索的路。咱們不能確定地說,咱們將在哪裏結束,但軟件開發的挑戰之一是,你只能基於目前能拿到手的不完善的信息做出決定。

相關文章
相關標籤/搜索