放棄微服務,我們爲什麼重回單體架構?

{"type":"doc","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"本文最初發表於Ben Nadel的"},{"type":"link","attrs":{"href":"https:\/\/www.bennadel.com\/blog\/3944-why-ive-been-merging-microservices-back-into-the-monolith-at-invision.htm","title":"","type":null},"content":[{"type":"text","text":"個人網站"}]},{"type":"text","text":",經作者同意由InfoQ中文站翻譯並分享。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"每當我們將"},{"type":"link","attrs":{"href":"https:\/\/www.bennadel.com\/invision\/co-founder.htm?redirect=https%3A%2F%2Fwww.invisionapp.com%2F%3Fsource%3Dbennadel.com","title":"","type":null},"content":[{"type":"text","text":"InVision"}]},{"type":"text","text":"的一個微服務合併回單體的時候,我都會發一條慶祝的推文。在這些推文中,我都喜歡包含一張關於滅霸的動圖,這張動圖就是滅霸將最後一顆無限寶石放到無限手套中。我覺得這張動圖非常合適,因爲集齊寶石給了滅霸巨大的能量,就像重新整合微服務給了我和團隊力量一樣。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"曾經有多次,許多人問我爲何要幹掉微服務。所以,我想和大家分享在Web開發領域這一段旅程的特殊見解。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/cf\/6b\/cf41252e946344939cyy02fd6a03806b.gif","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"我並不是“反微服務”"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"開篇,澄清一下,"},{"type":"text","marks":[{"type":"strong"}],"text":"我並不是反微服務"},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我將服務重新合併成單體並不意味着要將微服務從生活中徹底驅趕出去。這個任務的目標是"},{"type":"text","marks":[{"type":"strong"}],"text":"“調整”單體的大小"},{"type":"text","text":"。這樣做是爲了解決團隊的痛點。如果不能減少衝突,那麼我就不會花費"},{"type":"text","marks":[{"type":"strong"}],"text":"那麼多的時間(和機會成本)"},{"type":"text","text":"來提升、轉移和重構舊的代碼。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"image","attrs":{"src":"https:\/\/static001.infoq.cn\/resource\/image\/7b\/07\/7bfe4acc28e95f6632cd5bff60df5707.png","alt":null,"title":"","style":[{"key":"width","value":"75%"},{"key":"bordertype","value":"none"}],"href":"","fromPaste":false,"pastePass":false}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"每當這樣做的時候,我都冒着引入新bug和破壞用戶體驗的風險。將微服務合併成單體架構的過程中,雖然有時候很令人興奮,但總體還是令人感到恐懼的,而且需要"},{"type":"text","marks":[{"type":"strong"}],"text":"大師級的規劃、風險控制和測試"},{"type":"text","text":"。再次強調一遍,如果它不值得做的話,我就不會做了。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"微服務解決了技術和人的問題"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"爲了理解我爲何要銷燬一些微服務,首先很重要的一點就是要理解爲什麼一開始要創建這些微服務。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"微服務解決的是兩種類型的問題,也就是"},{"type":"text","marks":[{"type":"strong"}],"text":"技術的問題"},{"type":"text","text":"和"},{"type":"text","marks":[{"type":"strong"}],"text":"人的問題"},{"type":"text","text":"。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","marks":[{"type":"strong"}],"text":"技術的問題"},{"type":"text","text":"在於應用程序的某個方面給基礎設施帶來了過重負擔,這反過來又很可能會導致糟糕的用戶體驗(UX)。例如,圖像處理需要大量的CPU。如果CPU的負載變得非常高,這將會導致應用其他處理資源的餓死現象。這會影響系統的延遲。而且,如果更糟糕的話,那麼這會影響系統的可用性。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"另一方面,"},{"type":"text","marks":[{"type":"strong"}],"text":"人的問題"},{"type":"text","text":"與應用的關係並不大,它關係到你會如何組織團隊。在應用程序的特定部分,投入工作的人越多,開發和部署就會越慢,而且越容易出錯。例如,如果你有30個工程師都在競爭“持續部署(CD)”同一個服務,就會出現很多排隊的現象,這意味着很多本可以交付產品的工程師只能坐等輪到他們進行部署。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"早期,InVision微服務主要解決了“人”的問題"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"自8年前成立以來,InVision]一直都是一個單體系統,當時只有"},{"type":"text","marks":[{"type":"strong"}],"text":"3個工程師"},{"type":"text","text":"。隨着公司的成長和發展,系統的數量幾乎沒有增加,但是工程團隊的規模卻在快速擴張。幾年的時間,我們有了幾十名工程師,包括前端和後端,他們在同一個代碼庫上開展工作,所有的部署都會到同一個服務隊列中。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如前文所述,大量的人在同一個地方工作會產生很大的問題。不僅各種團隊會競爭相同的部署資源,而且每當遇到“緊急事件”的時候,多個團隊的代碼都需要回滾。而且,在處理事件的時候,所有團隊都不能進行部署。可以想象,這會在整個組織造成很多摩擦,對工程團隊和產品團隊均是如此。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"同時,“微服務”的出現是解決“"},{"type":"text","marks":[{"type":"strong"}],"text":"人的問題"},{"type":"text","text":"”的。一羣選定的工程師圍繞他們認爲的與團隊邊界相對應的應用組成部分開始劃分邊界。這樣做的目的是爲了讓團隊能更加獨立地工作,獨立地部署,從而發佈更多產品。早期的InVision微服務幾乎與解決技術問題毫無關係。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"如果你的邊界處理得很好的話,那康威定律是很不錯的"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果你從事微服務的話,那麼肯定聽說過“"},{"type":"link","attrs":{"href":"https:\/\/en.wikipedia.org\/wiki\/Conway's_law","title":"","type":null},"content":[{"type":"text","text":"康威定律"}]},{"type":"text","text":"”,它是由"},{"type":"link","attrs":{"href":"https:\/\/www.melconway.com\/","title":"","type":null},"content":[{"type":"text","text":"Melvin Conway"}]},{"type":"text","text":"在1967年提出的:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"任何設計系統(廣義定義)的組織,必然會產生以下設計結果:即其系統的結構就是該組織溝通結構的寫照。"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"該定律通常以“編譯器”爲樣例進行說明:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"blockquote","content":[{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果有四個組在從事一個編譯器相關的工作,那麼這個編譯器肯定是要分四個步驟的。"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"這裏的觀點在於,解決方案是圍繞團隊結構(和團隊通信開銷)進行“優化”的,而不一定是爲了解決特定的技術或性能問題。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在微服務出現之前,康威定律一般都是以負面的角度來進行討論的。比如,康威定律代表着你的應用規劃和組織比較糟糕。但是,在後微服務時代,康威定律有了更多的維度。因爲事實證明,如果你能將系統分解爲一組具有"},{"type":"text","marks":[{"type":"strong"}],"text":"內聚邊界"},{"type":"text","text":"的"},{"type":"text","marks":[{"type":"strong"}],"text":"獨立服務"},{"type":"text","text":",那麼就能以更少的bug發佈產品,因爲你所創建的團隊更專注於一組服務,而這些服務具備更窄小的職責範圍。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"當然,康威定律的收益在很大程度上依賴於在哪裏劃分邊界以及這些邊界"},{"type":"text","marks":[{"type":"strong"}],"text":"隨時間的推移該如何變化"},{"type":"text","text":"。這也就是我和我的Rainbow團隊的職責所在。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"多年來,"},{"type":"link","attrs":{"href":"https:\/\/www.bennadel.com\/invision\/co-founder.htm?redirect=https%3A%2F%2Fwww.invisionapp.com%2F%3Fsource%3Dbennadel.com","title":"","type":null},"content":[{"type":"text","text":"InVision"}]},{"type":"text","text":"必須要從組織和基礎設施方面進行發展。這意味着,在其背後,有一個較老的“遺留”平臺和一個不斷髮展的“現代”平臺。隨着越來越多的團隊遷移至“現代”平臺,這些團隊之前負責的服務則要移交給剩下的“遺留”團隊。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如今,我的團隊就是遺留團隊。這個團隊已經緩慢,但穩定地負責越來越多的服務。這意味着:人數變少了,但是代碼倉庫變多了,編程語言變多了,數據庫變多了,監控儀表盤變多了,錯誤日誌變多了。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"簡而言之,康威定律爲組織帶來的所有"},{"type":"text","marks":[{"type":"italic"}],"text":"收益"},{"type":"text","text":",隨着時間的推移,都變成“遺留”團隊的"},{"type":"text","marks":[{"type":"strong"}],"text":"負債"},{"type":"text","text":"。所以,我們一直在努力“調整”責任域,讓平衡迴歸康威定律。或者,換句話說,我們在嘗試改變"},{"type":"text","marks":[{"type":"strong"}],"text":"服務邊界"},{"type":"text","text":"以匹配"},{"type":"text","marks":[{"type":"strong"}],"text":"團隊的邊界"},{"type":"text","text":"。這意味着,將微服務重新合併爲單體架構。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"微服務的關鍵不在於“微”,而在於“合適的大小”"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"也許,微服務架構最糟糕的事情就是用了“微”這個字。“微”是一個毫無意義,但具有沉重負擔的術語,它實際上代表了歷史原因和人們的偏見。更合適的術語應該是“合適的大小”。微服務的目的從來不是成爲“小的服務”,而是成爲“大小合適”的服務。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"“微”這個術語毫無意義,不代表任何實際的內容。而“合適的大小”意味着服務經過了"},{"type":"text","marks":[{"type":"strong"}],"text":"恰當地設計"},{"type":"text","text":",以滿足其需求:它負責“合適數量”的功能。而且,至於什麼是“合適”並不是一個靜態的概念,它取決於團隊,即團隊的技能集、組織的狀態、投資回報率(return-on-investment,ROI)的計算、持有成本以及該服務運行的時間點。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"對我的團隊來說,“合適的大小”意味着更少的代碼倉庫,更少的部署隊列,更少的語言以及更少的運維儀表盤。對於這個非常小的團隊來說,“合適的大小”更多的是關於“人”,而不是關於“技術”。所以,就像InVision最初引入微服務是解決“人的問題”一樣,我們團隊現在摧毀這些微服務也是爲了解決“人的問題”。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"姿態是一樣的,只是表現形式有所不同。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我爲團隊在遺留平臺上所付出的努力而感到自豪。雖然團隊規模不大,但是我們利用自己所擁有的東西完成了很多的工作。我把這種成功歸功於我們對遺留平臺的深入瞭解,"},{"type":"text","marks":[{"type":"strong"}],"text":"積極的實用主義"},{"type":"text","text":",以及不斷努力設計一個能對應我們能力的系統,而不是試圖擴大我們的能力以滿足系統需求。這可能聽起來很狹隘,但是,這是我們團隊及其所擁有的資源在這個時刻唯一可行的方法。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"後記1:大多數技術並不需要“獨立擴展”"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"支撐創建獨立服務的論據之一就是這些服務是可以“獨立擴展”的。也就是說,可以更有針對性地提供服務器和數據庫,以滿足服務的需求。因此,與其創建大型的服務卻只擴展其中一部分功能,我們能夠在獨立擴展其他服務的同時,讓某些服務保持規模很小的狀態。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"在所有關於爲什麼說獨立服務是一件“好事”的理由中,這個理由經常被提及,但是在我(有限的經驗)看來,這通常是不成立的。除非某項功能是"},{"type":"text","marks":[{"type":"strong"}],"text":"CPU密集"},{"type":"text","text":"、"},{"type":"text","marks":[{"type":"strong"}],"text":"IO密集"},{"type":"text","text":"或"},{"type":"text","marks":[{"type":"strong"}],"text":"內存密集"},{"type":"text","text":"的,否則獨立的可擴展性可能並不是你需要擔心的“能力”。很多時候,你的服務器都在等着做事情,爲一個應用程序添加“更多的HTTP路由處理程序”並不會突然耗盡它所有的資源。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"如果我能回到過去,"},{"type":"text","marks":[{"type":"strong"}],"text":"重新嘗試我們的微服務"},{"type":"text","text":",我100%會先關注所有 “CPU密集”的功能:圖像處理和調整大小、縮略圖生成、PDF導出、PDF導入、使用"},{"type":"codeinline","content":[{"type":"text","text":"rdiff"}]},{"type":"text","text":"的文件版本管理、ZIP壓縮文件生成。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我會沿着這些邊界組織團隊,讓他們創建“純的”服務,只處理輸入和輸出(即,沒有“集成數據庫”,也沒有“共享文件系統”),這樣其他所有的服務都可以使用它們,同時保持了松耦合。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我並不是說這樣就能解決我們所有的問題--畢竟我們的“人的問題”比 “技術的問題”要多。但是,它可以解決一些“合適性”的問題,從長遠來看,這可能會讓生活變得更輕鬆一些。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"heading","attrs":{"align":null,"level":2},"content":[{"type":"text","text":"後記2:微服務也有純經濟方面的成本"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"服務並不是在抽象地運行:它們要在服務器上運行,與數據庫通信,報告度量指標並且還會生成日誌條目。所有的這些都需要真正的經濟成本。所以,儘管“lambda函數”在我們不使用它們的時候,不會花掉我們的錢,但是大多數“微服務”肯定還是會花錢的。特別是當我們爲了創建一個“高可用”的系統而需要維護冗餘的時候。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"我的團隊將微服務重新合併成單體架構對業務帶來了切實的經濟影響(這種影響是正面的)。這種影響並不巨大,我們只是在談論一些小型的服務,但也不是微乎其微。所以,在將系統合併之後,我們不僅得到了“人”的方面的收益,還得到了實際的經濟收益。"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"text","text":"原文鏈接:"}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null},"content":[{"type":"link","attrs":{"href":"https:\/\/www.bennadel.com\/blog\/3944-why-ive-been-merging-microservices-back-into-the-monolith-at-invision.htm","title":null,"type":null},"content":[{"type":"text","text":"https:\/\/www.bennadel.com\/blog\/3944-why-ive-been-merging-microservices-back-into-the-monolith-at-invision.htm"}]}]},{"type":"paragraph","attrs":{"indent":0,"number":0,"align":null,"origin":null}}]}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章