作者 | Ashley Davis
譯者 | 明知山
策劃 | 丁曉昀
持續之戰:單體架構與微服務
"從許多方面來看,微服務就是一種僵尸架構,另一種拒絕死去的知識傳染病菌。這種病菌從 J2EE(遠程服務器 Bean,有人記得嗎?)的黑暗時代開始,經歷了 WS-Deathstar 的胡鬧,現在又以微服務和無服務器的形式存在。"
—— David Heinemeier Hansson (來源)
隨著亞馬遜云科技在他們的官博中宣稱他們放棄了微服務并回歸單體架構,單體架構與微服務之間的戰爭再次爆發。
你對此有何看法?你是支持微服務還是單體?但我想說的是,這種區分有點虛幻,因為人們爭論的只是一種虛構的概念:微服務與單體只是整個故事的一個組成部分。
亞馬遜云科技的這篇文章被視為他們(作為微服務的長期支持者)已經回頭轉向單體架構的證據。
盡管文章的標題明顯是為了引起關注,但從內容上看,似乎是關于他們從函數即服務向微服務架構(如果不是比微服務更大的分布式應用程序服務)的轉變。
但在我看來,這并不重要。這只能說明,亞馬遜云科技的一個團隊承認他們嘗試的架構在一段時間后不奏效,然后嘗試了不同的架構,得到了更好的效果。但這又怎樣?這只是好的軟件開發應該經歷的正常過程。
我們都希望專注于最重要的事情,為我們的客戶做正確的事情,在微服務與單體的爭論中選邊站隊只會給我們造成阻礙。有時候,我們需要微服務。有時候,我們需要單體架構。(我還不確定我是否會需要 FaaS——但我保持開放的態度)。大多數情況下,我們需要在兩個極端之間找到平衡點。
為什么我們害怕微服務?
當然,與單體相比,微服務更難 —— 我承認這一點。但如果你有了自動化的微服務架構,這個論點就站不住腳了。我曾經使用過的一些無縫集成又容易使用的系統就是擁有良好自動化的微服務。另一方面,我曾經參與的一個最困難的項目是一個古老的大單體,幾乎沒有自動化。我們的日子不會因為選擇了單體而變得輕松。
對微服務的害怕有沒有可能是對微服務過度炒作的反噬?是的,微服務已經被過度炒作了。微服務不是靈丹妙藥。像所有潛在的解決方案一樣,它們并不適用于所有場景。當你使用一種錯誤的架構來解決某個問題(或更糟糕的是,管理層強制要求使用錯誤的架構)時,我可以理解你為什么會對這種架構充滿厭惡。
是否有一部分害怕是來自微服務早期的日子?十年前,微服務確實使開發變得更加困難。但從那時起,工具和平臺已經取得了長足的進步,現在比以往任何時候都更容易進行自動化,給微服務開發帶來更加無縫和愉快的體驗。
也許,一部分害怕來自對復雜性的感知,我認為這是其中很大的一部分。人們會自然而然地害怕(或至少想要避免)復雜性。我說可感知的復雜性,因為不僅僅是微服務會變得復雜,單體也會 —— 只是時間問題。然而,對于微服務來說,復雜性是公開的,所有人都可以看得到,我們必須早日加以應對。在我的“BootstrApping Microservices”一書中,我稱之為將痛苦提前,以便能夠在開發過程中更容易、以更低的成本應對復雜性。
不幸的是,在現代軟件開發中,我們無法逃避復雜性。我們的應用程序正在變得越來越龐大和復雜 —— 即使是普通的單體架構也注定會變得無比復雜。
在現代的大規模軟件開發中,我們無法避免復雜性。我們需要使用工具來幫我們管理復雜性,避免它們阻礙我們的開發過程或壓垮我們。
為什么微服務看起來如此困難?
"你必須達到這道門檻才能使用微服務。"
—— Martin Fowler (來源)
構建分布式應用程序(不僅僅是微服務)需要更高的技術熟練度。管理大量的服務意味著我們必須擁有自動化管理工具。為了了解我們的服務在做什么,我們還需要跟蹤很多東西。隨著服務之間的交互變得越來越多,了解這些信息的困難程度將呈指數級增加。
假設你是一個小團隊或在開發一個小項目,在不需要微服務的場景中采用了微服務,或者如果你不愿意付出構建和運行分布式系統所需的技能和技術投入,你就不能指望從中得到良好的體驗。
另一個可能的痛點是未能適當地將服務與領域對齊。我曾見過一些微服務應用程序與技術對齊但沒有與業務需求對齊,導致存在過多的服務和一個不必要的難以管理的系統。將服務分得太小,不必要地增加了系統的復雜性和難度,這是一個問題。
如果你無法正確地將架構與領域對齊,那么無論使用單體還是微服務,都將遇到嚴重的問題 —— 隨著服務數量的增加,這些問題將會被大幅放大。微服務既能帶來性能方面的伸縮性,也會放大已經存在的問題。
這只是一個伸縮性問題嗎?
"如果你無法應對單體的復雜性,憑什么認為微服務就是良方?"
—— Simon Brown (來源)
微服務的真正問題是它們只是放大了已經存在的問題嗎?
一個糟糕的微服務實現比糟糕的單體架構糟糕 X 倍(X 是你的分布式應用程序中服務的數量)。隨著分布式應用程序中通信路徑的指數級增加,情況甚至更糟。
如果你沒有合適的工具、技術、自動化、流程和組織來應對單體,那么你憑什么認為你可以處理好微服務?
微服務不僅帶來性能和開發方面的可伸縮性,也帶來了困難程度的伸縮。如果你在構建和維護單體架構時感到困難,轉向微服務也并不會給你帶來任何好處。
微服務應用程序也是一種單體,只是服務的數量增加了、服務的大小變小了而已。如果疲于應對單體架構,卻認為微服務是良方,那么請再三思。
我認為微服務不僅在性能和開發方面帶來了可伸縮性,也帶來了困難程度的伸縮。微服務有它的優點,但這些優點并不是完全免費的。
微服務的成本
"微服務并非免費午餐。"
—— Sam Newman (摘自“Building Microservices”)
微服務到底是什么?為什么我們要將應用程序劃分為獨立的服務?
微服務有許多眾所周知的好處:
- 可伸縮性
- 性能
- 開發團隊
- 容錯性
- 獨立(和較低風險)部署,支持快速開發
- 開發者賦權
- 可丟棄(Disposability)
- 管理復雜性
但這些好處并非微服務的全部,我們也需要為此付出成本:
- 更高水平的技術技能
- 更好的自動化、管理和可觀察性系統
- 處理可伸縮性難題
對于任何一種工具、技術、架構或任何我們想要使用的東西,我們必須問自己一個問題:收益是否超過了成本?如果收益超過了成本,你將在使用這些技術時獲得良好的體驗。如果沒有,你將在痛苦的時光中度過。
管理復雜性
"微服務支持大規模、復雜應用的持續部署。"
—— Chris Richardson (來源)
微服務有許多優勢,但我們使用它們的真正理由是,它們可以幫助我們管理應用程序日益增長的復雜性。
沒錯,微服務不是復雜性的根源,而是解決復雜性的方法。
所有的應用程序都將變得復雜,即使是單體也無法避免。微服務為我們提供了將復雜性分解為更小、更簡單、更易管理的構建塊的工具。
微服務通過將復雜性分解為簡單而隔離的部分來幫助我們管理復雜性。我們也可以在單體架構中做到這一點,但你需要一個紀律嚴明和積極主動的團隊來保持設計的完整性,不至于變得一團糟。
我們可以使用微服務來抽象和將軟件組件化。當然,我們也可以在單體架構中做到這一點,但微服務還為我們提供了牢固的組件邊界,更不用說其他優勢了,如獨立部署和故障隔離。
可能性頻譜
"不存在放之四海而皆準的架構模式。"
—— Dr. Werner Vogels (來源)
我在本文一開始問了一個問題:你是支持微服務還是單體?
回到本文的標題,這不是一個非此即彼的選擇。從一個大服務(單體)到許多小服務(微服務),在它們之間還有許多其他可行的選擇。
這不只是單體與微服務二選一,它們之間存在一種可能性頻譜。如果你將自己固定在支持單體或微服務的立場上,就將錯過它們之間豐富的架構多樣性。
你不必人為地將自己對準頻譜的任意一端。你甚至不必將自己固定在其中任意的特定位置。盡管一些人想讓你這樣認為,但并不存在所謂的正確的立場。你選擇的位置應該與你的團隊、業務、項目或客戶對齊。只有你可以決定應該處在頻譜的哪個位置。
投資回報遞減
隨著你在頻譜的右側移動,你將獲得微服務的好處,但向右移動也伴隨著成本和困難的增加。我們需要確保轉向微服務的成本是我們愿意承擔的。
如果你不是為了管理復雜性,不需要微服務的其他好處,或者在管理單體的自動化和技術方面存在困難,那么你應該盡量留在頻譜的左側。隨著你需要微服務的程度的增加,應該朝著頻譜的右側靠近。
隨著投資回報遞減,一直邁向完美的微服務烏托邦可能是不值得的,但只走其中的一部分道路可能會帶來高回報。
此時我們要清楚地認識到,我們不需要達到(我喜歡稱之為)微服務烏托邦的程度才能開始享受無服務的好處。無論我們是否達到了頻譜的另一側,我們只要朝著頻譜的右側移動一定程度,都會得到切實的好處!
有很多原因使我們不想邁向完美的微服務。(首先,誰來決定完美的定義?)當我們開始向右側推進時,將看到巨大的回報。但隨著繼續向前推進,投資回報開始遞減。我們越是朝著更小的服務前進,成本就會超過好處。在雜亂復雜的現實世界中,實現完美的微服務是很困難的,更不用說這其實是不必要的。但這并不意味著朝著那個方向前進不會有所裨益。
混合模型
如果不需要一直推進到微服務一側,那應該在哪里停下來呢?答案是在中間的某個位置,在這個位置有一些權衡可以提高我們的開發速度和能力,但成本不會超過好處。
我喜歡將在中間的某個位置看作是兩全其美。是的,我們可以擁有單體(或多個單體),單體周圍環繞著一些微服務。持有這種務實立場的我是否成了某種異教徒?這種架構的實際好處在于我們可以將單體的好處與微服務的好處混合起來。單體代碼庫的便利性和簡單性,加上在必要時可以利用的微服務的靈活性、可伸縮性和其他好處,使得這種架構成為一個理想的選擇。如果有必要,我還可以逐步從單體拆分出單獨的微服務,讓某些功能或任務可以從中受益。
混合模型并不是什么新想法,這就是現實世界通常的樣子(在中間的某個位置),盡管人們在網絡上繼續爭論不休。
David Heinemeier Hansson(單體支持者)似乎很喜歡這個想法,他將其稱為城堡架構。
大小真的重要嗎?
"也許‘Micro’是一個具有誤導性的前綴。它并不一定是‘小’的意思。大小實際上并不重要。"
—— Ben Morris (source)
服務越小,就越 Micro,作用就越小,我們就需要越多的服務。隨著我們減小服務的大小并增加服務的數量,困難程度也會提升。
或許,我們應該停止專注于微服務“Micro”的部分。我認為這會導致人們將自己的服務變得過于小,而這一定會導致在使用微服務時遇到困難。
我甚至不確定我們是如何如此專注于使它們變得盡可能小的。我們的意圖是將軟件拆分成不同的部分,分離責任,讓每個部分都比整體簡單,從而更容易管理系統的復雜性。但如果服務過于小,我們可能會被復雜性淹沒,無法管理好它們。
盡管每個人似乎都有自己關于微服務大小的看法,但現實是,微服務的大小沒有固定標準。
所以,我們應該停止爭論服務的大小,我們應該談論的是“合適大小”的服務,也就是適合實際情況的適當的大小——單體或者是頻譜較小的一端。我們的服務,無論大小如何,都應該根據業務和領域來決定。微服務大小只是后話,整體的組織更為重要。
問題不在于使服務變得盡可能小,服務小到超過某個程度就會適得其反。它們越小,就必須與系統的其余部分進行更多的交互才能完成任務。交互越多,我們就需要付出更高的網絡傳輸成本,更不用說這會使得它們之間的交互變得更加難以理解。我們需要在服務大小和服務有多喋喋不休(Chatty)之間取得良好的平衡(感謝 Damian maclennan 提供了"喋喋不休"一詞)。
選擇對你來說有意義的服務大小,一些服務比其他服務大,這并不是什么問題。請不要讓你的強迫癥決定服務的大小——這可能會阻礙一個出色的架構的出現。將服務變得更大或更小本質上沒有對錯之分,只要你找到適合自己的。
不要害怕改變你的想法
"老實說——我以前也這么做過,從微服務轉向單體,然后再轉回來。兩個方向都有嘗試過。"
—— Kelsey Hightower
有時候,為了了解新技術是否適合我們的項目,我們必須進行嘗試。所以不要害怕嘗試新技術,不要害怕嘗試微服務或混合模型,看看它們是否有效。
嘗試之后不要害怕改變你的想法,并撤銷之前做出的決定。承認某些事情不成功并不是件壞事,這是我們為了取得成功所需要做的事情。嘗試不同的事情,進行各種實驗,并放棄那些沒有成功的事情。因為微服務在特定項目上不適用并不意味著它們對于其他團隊或項目也是糟糕的選擇。
或者更好的是,保持開放的思維,這是不讓自己與新思想和新思維隔絕的最佳方式,這些可能是你做好下一個項目所需要的。
延伸閱讀
Bootstrapping Microservices(https://www.bootstrapping-microservices.com/)
Rapid Fullstack Development(https://rapidfullstackdevelopment.com/)
查看英文原文:
https://www.infoq.com/articles/monolith-versus-microservices/