Martin Fowler談微服務的優缺點

不少開發團隊已經認識到微服務架構比單體架構更優越。可是也有其餘團隊感受到這是一種消弱生產力的負擔。就像任何軟件架構,微服務架構一樣有利弊。爲了能作出一個明智的選擇,你必須瞭解這些應用並將它們運用到你特定的環境中。html

微服務.png

 

模塊化

微服務最大的好處是對功能模塊的劃分。這是個既重要又奇怪的好處,由於理論上沒有理由來解釋爲什麼微服務比單體架構有更強大的模塊劃分。

那到底什麼是我說的模塊邊界。我想大多數人贊成,將軟件劃分紅多個模塊,很是好:彼此就能夠分離解耦。若是我須要改變系統的一小部分,大多數的時候我只須要弄清楚這一小塊,而後作些改動,咱們會發現小變更真的很容易。對於任何程序而言,好的模塊化結構很是有用,特別是當軟件的規模變大,模塊化會顯得格外重要。也許,它會變得更重要,由於團隊的規模也在增長。

提倡微服務,須要快速介紹一下康威定律,該定律認爲一個軟件系統的結構反映了團隊的溝通結構。對於較大的團隊,特別對於那些分散在各地的團隊,對軟件實施結構化顯得尤其重要,跨團隊之間的溝通與一個團隊內部溝通相比,將會變得不那麼頻繁且更加正式。微服務容許每一個團隊用相似的溝通模式來照看相對獨立的模塊單元。

正如我前面所說,沒有理由能夠解釋爲什麼一個單體系統不該該擁有一個良好的模塊化結構[1]。可是不少人都觀察到這彷佛不多見,所以大雜燴成了最多見的架構模式。事實上單體架構這種固有的困惑,驅動一些團隊開始使用微服務架構。模塊的解耦可以起做用,是由於模塊的邊界就是模塊之間引用的障礙。麻煩的是,一個單體系統,一般都很容易繞過障礙。這樣作,多是構建功能時有用的技術捷徑,但是呢,若是普遍運用這種方法,將削弱模塊化的結構和下降團隊的生產力。將模塊放入獨立的服務,這樣作使模塊的邊界更爲牢固,使這種自殺式的解決方案更難實現。

耦合的重要部分是持久化的數據。微服務的關鍵特徵是去中心的數據管理,也就是說每一個服務管理它本身的數據庫,其它的服務必須經過該服務的API來交互。這就會消除集成數據庫,這是大系統很是討厭耦合的主要緣由。

值得強調的是在一個單體系統中,使用模塊化徹底可能,可是它須要紀律來保證。一樣地,你也可能獲得微服務的大雜燴模式,可是對於自己已經是微服務的架構,要犯這樣的錯仍是不太容易的。在我看來,使用微服務,能夠幫助你實現更好的模塊化。若是你對團隊紀律頗有信心,那麼可能會消除這一優點,不過,隨着團隊的規模增長,保持紀律會變得愈來愈,這也就意味着維護模塊邊界將顯得更爲重要性。

若是你很差好管理模塊的邊界,這個優點就會變成障礙。這就是單體優先策略的兩個主要緣由之一,也是爲什麼我更傾向於較早使用微服務,你只能在一個領域瞭解得很是透徹。

但我如今不會在這方面作出警告。只有通過時間的洗禮,你才能真正講出要如何才能把一個系統的模塊化維護好。因此只有咱們看到微服務系統已經運行好多年,才能夠評估它是否會帶來更好的模塊化特性。並且,早期接納者更有才華,也就是說在咱們可以評估通常團隊構建的微服務系統的模塊化優點以前,還有好幾年的延遲。因此與其和高水平的團隊比較成果,還不如比較那些已經使用單體架構的軟件帶來的變化,這是一個棘手的違背事實的評估。

全部我如今能作的,就是聽聽那些我認識的人,他們使用微服務架構的早期經驗。他們的判斷就是微服務能讓他們更容易去維護功能模塊。

有一個案例特別有意思。有一個團隊作了一個錯誤的決定,在一個不那麼複雜的系統上面使用微服務。後來這個項目碰到了問題,須要幫助,而後不少人就跑了進來。這方面,微服務仍是有所幫助的,由於這個系統可以吸引開發者的快速涌入,和單體架構相比,團隊更容易擴張。最終這個項目的進度大大超過使用單體架構的預期,使整個團隊遇上進度。固然也有負面的,和單體架構相比,微服務的方式耗費了更多的人力,可是微服務的架構可以支持將來更大的規模。

若是你想要知道更多有關於如何構建微服務系統,Sam Newman的這本書是很重要的資料。docker

分佈式特性

微服務採用分佈式系統來提升模塊化。可是分佈式軟件有一個主要的缺陷,就是分佈式系統自己。一旦你開始玩分佈式系統,你就會碰到一堆複雜的問題。我不認爲微服務社區對分佈式系統所帶來的成本沒有概念,可是複雜性也確實存在。

首先是性能。這時候,你不得不以一種不常見的方式,看着進程內的函數調用轉變成性能的瓶頸,遠程調用是很慢的。若是你的服務調用了不少遠程服務,這些遠程服務自己也要調用了另一些遠程服務,這些響應時間加起來,就會帶來很恐怖的延遲特徵。

固然你有辦法減小延遲。首先,你能夠增長調用的粒度,減小調用的數目。這會使你的編程模式變得複雜,使得你必須想清楚如何批量處理跨服務交互。因爲你必須調用至少一次這些全部合做的服務,所以到目前爲止,你能作的就這麼多了。

第二種方法就是使用異步通訊。若是六個服務異步並行調用,延遲只會是那個最慢的調用,而不是全部調用延遲的總和。這大大改善了性能,但也帶來了認知成本。異步編程很難,你很難用好它,並且很難調試。但我聽到的大多數微服務的例子,都須要異步來得到預期的性能。

速度以後就是可靠性的問題。你指望in-process函數調用可以成功,但是一個遠程調用可能在任什麼時候間失敗。在不少的微服務中,甚至有不少的潛在的故障點。明智的開發人員知道這些,爲可能發生的故障事先設計。你爲異步協做作的方案,也適應於故障處理,還可提升服務的彈性。然而,這些補償仍然不夠,仍然有着額外的複雜性,你須要弄明白每個遠程調用失敗的後果。

這就是分佈式計算最主要的兩個難題

對於這個問題,還有一些要注意的地方。首先,不少這類的問題出如今單體架構規模擴充的時候。不多有單體架構能夠真正獨立運行,一般是跟其餘系統一塊兒,這些系統大部分是遺留系統。和這些系統經過網絡進行交互,一樣會碰到這些相似的問題。這就是爲什麼不少人都傾向於更快轉移到微服務架構,來處理遠程系統的交互問題。這個問題,一樣也和經驗有關係,更熟練的團隊更有能力處理分佈式特性所帶來的問題。

固然,分佈式特性永遠都是一個成本。我老是不太願意打分佈式這張牌,由於想到不少不少人,因低估這些難題而太快地引入了分佈式系統。數據庫

最終一致性

我想你應該知道,網站的更新着實須要一點耐心。更新某一個東西以後刷新屏幕,但是更新的東西尚未出現。你等了一兩分鐘後,它出現了。

這是一個很是惱人的可用性問題,幾乎能夠確定是因爲最終的一致性形成的。你的更新被節點P收到,但是呢,你的請求卻被另外一個節點G處理。直到節點G從節點P那兒獲得更新以前,你一直處於數據不一致的狀態。最終,它會變成一致的,但在這以前,你會疑惑是否是有什麼東西弄錯了。

像這樣的不一致是使人惱火的,但他們能夠更嚴重。業務邏輯會停滯在對不一致的信息上作出決策,當這種事發生時,在不一致的窗口關閉以前,也難以診斷出到底什麼出了問題。

微服務帶來了最終一致性的問題,是由於他們堅持對去中心的數據管理,這種堅持值得稱讚。單體架構,你能夠一次更新一堆東西。微服務則須要多個資源的更新和分佈式的處理,這確實頭疼。因此如今,開發者須要意識到一致性問題,在寫任何代碼以前,弄明白如何檢測數據的不一致。

單體架構在這些問題上一樣不能全身而退。隨着系統的增加,更須要使用緩存來提升性能,緩存失效是另外一個困難的問題。大多數應用程序須要脫機鎖,以免長期的數據庫事務處理。外部系統須要更新,不能與事務管理器協調。商業流程每每更具寬容的不一致性,由於企業對可用性要求更高(業務流程,一直以來對CAP理論都是一種直覺上的理解)。

和其餘分佈式問題同樣,單體架構也不能徹底避免非一致性問題,但它們受到的困擾很少,特別當它們規模很小時。編程

獨立部署

微服務是DevOps革命後第一新的軟件架構。-- Neal Ford

模塊化和分佈式系統的複雜性一直伴隨着我整個職業生涯中。可是有一件事情發生了明顯的變化,就是在過去的十年中,有關生產環境的發佈。在二十世紀,生產環境的發佈幾乎老是痛苦且罕見的事情,週末的白天或晚上部署一些能用的軟件。可是如今呢,熟練的團隊頻繁發佈到生產環境,許多團隊實行持續交付,使他們一天可以在生產環境發佈不少次。

這種轉變已經對軟件產業產生了深遠的影響,並與微服務運動深深交織在一塊兒。當部分的小變化可能致使整個部署失敗,微服務終於被單體架構的部署難題所激發出來。微服務的一個關鍵原則是,每一個服務都是系統的一個組件,都可獨立部署。因此如今當你作出改變時,你只須要測試和部署一個小服務。若是你把它搞砸了,你不會把整個系統都搞砸。畢竟,事先對故障進行了設計,即便失敗了,你的組件也不該該中止其餘部分的系統工做,儘管功能上有些退化。

這種關係是雙向的。因爲許多微服務須要頻繁部署,統一部署行爲顯得尤其重要。這就是爲何應用的快速部署和快速配置是微服務的先決條件。對於任何以此爲基礎的服務,你都須要作持續的交付。

持續交付的好處是減小了由想法變成軟件的時間。那麼,團隊能夠快速響應市場變化,並快於競爭對手先引入新的功能。

儘管許多人認爲持續交付是使用微服務的一個緣由,但值得注意的是,即便單體架構也能夠持續交付。Facebook和Etsy是兩個最好的例子。還有一些嘗試微服務的例子,由於多個服務須要認真協調才能發佈,所以沒法獨立部署[2]。同時我也聽到不少人認爲使用微服務能更容易作持續交付,我是不太相信模塊化可使持續發佈更容易,儘管它能夠大大提升交付的速度。數組

運維的複雜性

可以迅速部署獨立的小單位,是項目開發的一大福音,但因爲幾十個應用如今轉變爲幾百個小的微服務,給運維額外增長了負擔。許多組織會發現,處理這樣一個迅速變化的工具,有一種使人望而卻步的難度。

這增強了持續交付的重要性。而持續交付是單體架構一項有價值的技能,也是一個微服務所必須的。若是沒有自動化協做,持續交付也沒法處理那麼多的服務。運維的複雜性也是由管理這些服務和監控的需求的增長而增長。運維的複雜性對單體架構的應用也有所幫助,不過對微服務來講,這是必然的。

微服務的支持者指出,因爲每一個服務更小,因此更容易理解。但風險在於,複雜性並無消除,它只是轉移到服務之間的相互聯繫中。這會增長運維的複雜性,好比調試、跨服務的難度。良好的服務邊界的選擇將減小這個問題,但若是用錯地方,則更糟糕。

處理這種運維複雜度,須要一個新的技能和工具——重點是技能。工具仍然是不成熟的,但個人直覺告訴我,即便有更好的工具,微服務還得靠高技能。

然而,對技能和工具的需求不是解決運維複雜性最難的部分。想要高效地解決,你還須要引入一個DevOps文化:開發者和運維之間的緊密合做,每一個人都參與軟件交付。文化變革是困難的,尤爲是在更大和更老的組織中。若是你不改變這個技能和文化,單體架構的應用只會受到阻礙,而微服務應用則會受到創傷。緩存

技術的多樣性

因爲每一個微服務都是一個獨立的部署單元,你有至關的自由選擇須要的技術。微服務能夠用不一樣的語言,使用不一樣的庫,並使用不一樣的數據存儲方式。這使得團隊能夠選擇合適的工具來工做,有些語言和庫更適合某些類型的問題。

技術多樣性一般以最佳的工具爲中心進行討論,但每每微服務最大的好處確是更使人頭疼的版本問題。在單體架構中你能夠只使用一個單一的版本庫,這種狀況常常致使升級出現問題。系統的一部分可能須要升級,來實現使用它的新功能,但不能由於升級而中斷系統的另外一部分。處理庫的版本問題是其中的一個難題,由於隨着代碼庫的增大,難度會呈指數級增加。

這裏有一個風險,有這麼多的技術多樣性,開發團隊會被壓倒。我所認識的大多數組織都鼓勵有限的一組技術。這種鼓勵是經過提供共同的工具來支持監測,使它更容易將服務穩定在一個小的通用環境中。

不要低估了支持使用新技術的價值。用單體架構系統,早期對語言和框架的決定是很難逆轉的。通過十年左右,這些的決定可能會限制團隊並使團隊陷入尷尬的技術境地。微服務讓團隊嘗試新工具,並逐步一次遷移系統的一個服務,使新老技術有所關聯。安全

其餘因素

在我看來,上面的因素是做爲首要權衡指標來考慮的。這裏要討論的一些事情,我認爲就沒那麼重要了。

微服務的支持者們常常說服務更容易擴展:一個服務獲得大量的負載,你就能夠擴展,而不用對整個應用進行擴展。然而,我努力回憶起一個過往的經驗報告,它使我相信,和千篇一概的應用複製相比,它其實是更有效地進行選擇性擴展。

微服務容許你隔離敏感數據以及給數據增長安全性。此外,在保證微服務間交互安全的前提下,微服務難以被攻入。安全問題愈來愈重要,這能夠成爲使用微服務的主要考慮因素。即便不用微服務,對於單體架構的系統建立隔離服務來處理敏感數據,也是很常見的。

批評者說微服務應用的測試要比單體架構的應用難度更大。雖然這個真正的困難部分來自於分佈式應用程序的複雜性,但仍是有好的方法能夠測試微服務。在這裏,最重要的是要有紀律,要認真測試,單體架構和微服務應用的測試方法的區別只是第二位的。cookie

總結

任何有關架構的綜述文章都會受到通常性建議的限制。因此讀一篇這樣的文章不能幫助你作決定,但這樣的文章能夠幫助你確保考慮到你應該考慮的各類因素。這裏對不一樣的系統,成本和收益作了不一樣的權重,甚至成本收益會被顛倒過來(在更復雜的系統中強模塊化更好,但對於一個簡單的系統,這就增長了障礙),你所作的任何決定取決於環境中使用條件,評估哪些因素最重要,以及它們如何影響你的特定評估條件。此外,咱們對微服務架構經驗相對有限。在一個系統成熟後,你一般只會在這個體系中決定相應的架構。咱們尚未不少關於長期運行的微服務架構的實例。

單體架構和微服務並非簡單的二選一。二者都是模糊的定義,意味着大多數系統都將在一個模糊的邊界區域。固然也還有其餘系統,不適合這兩個類別的。大多數人,包括我本身,討論微服務時用單體架構做對比,這是由於它們更常見,但咱們必須記住,仍是有系統不屬於這兩類的。我認爲,單體架構和微服務是架構設計領域重要的兩部分。它們值得被討論,由於它們存在有趣的特性,以及有用的討論,可是沒有合適的架構師能夠對它們在架構設計領域進行一個全面的區分。

總結起來,微服務的好處:微服務提升了生產效率,但同時也帶來了複雜性。因此若是你能夠用單體架構管理好你的系統,那麼就無需微服務。

對微服務的討論不該該讓咱們忘記了更重要的問題,驅動軟件項目成功和失敗的重要因素。軟因素如團隊中人的素質,以及他們如何彼此合做,與領域專家的溝通能力,這都會對是否使用微服務有更加的影響。在純技術層面上來說,更重要的是把重點放在乾淨的代碼、完善的測試,並持續關注架構的演化進步。網絡

腳註

[1] 有些人認爲「單體架構「是一種侮辱,老是意味着很糟糕的模塊化結構。在微服務世界,大多數人不這樣作,他們將單體架構定義爲將整個應用構建爲一個獨立的單元。固然,微服務倡導者相信大多數單體架構最終會變成大雜燴,但我不知道有誰會認爲創建一個結構良好的單體架構毫無可能。

[2] 能獨立部署服務是微服務定義的一部分。因此這麼說仍是有道理的,即必須在其部署時協調服務的架構不是微服務架構。也能夠這麼說,不少團隊嘗試微服務架構而陷入麻煩是由於他們最終不得不協調多個服務來部署。架構

原文連接:Microservice Trade-Offs

相關文章
相關標籤/搜索