我們公司放棄了微服務(wù),重回單體架構(gòu)
作者 | Ben Nadel
每當(dāng)我們將 InVision 的一個(gè)微服務(wù)合并回單體的時(shí)候,我都會(huì)發(fā)一條慶祝的推文。在這些推文中,我都喜歡包含一張關(guān)于滅霸的動(dòng)圖,這張動(dòng)圖就是滅霸將最后一顆無限寶石放到無限手套中。我覺得這張動(dòng)圖非常合適,因?yàn)榧R寶石給了滅霸巨大的能量,就像重新整合微服務(wù)給了我和團(tuán)隊(duì)力量一樣。

曾經(jīng)有多次,許多人問我為何要干掉微服務(wù)。所以,我想和大家分享在 Web 開發(fā)領(lǐng)域這一段旅程的特殊見解。
開篇,澄清一下,我并不是反微服務(wù)。
我將服務(wù)重新合并成單體并不意味著要將微服務(wù)從生活中徹底驅(qū)趕出去。這個(gè)任務(wù)的目標(biāo)是 “調(diào)整”單體的大小。這樣做是為了解決團(tuán)隊(duì)的痛點(diǎn)。如果不能減少?zèng)_突,那么我就不會(huì)花費(fèi) 那么多的時(shí)間(和機(jī)會(huì)成本) 來提升、轉(zhuǎn)移和重構(gòu)舊的代碼。

每當(dāng)這樣做的時(shí)候,我都冒著引入新 bug 和破壞用戶體驗(yàn)的風(fēng)險(xiǎn)。將微服務(wù)合并成單體架構(gòu)的過程中,雖然有時(shí)候很令人興奮,但總體還是令人感到恐懼的,而且需要大師級(jí)的規(guī)劃、風(fēng)險(xiǎn)控制和測(cè)試。再次強(qiáng)調(diào)一遍,如果它不值得做的話,我就不會(huì)做了。
為了理解我為何要銷毀一些微服務(wù),首先很重要的一點(diǎn)就是要理解為什么一開始要?jiǎng)?chuàng)建這些微服務(wù)。
微服務(wù)解決的是兩種類型的問題,也就是 技術(shù)的問題 和 人的問題。
技術(shù)的問題 在于應(yīng)用程序的某個(gè)方面給基礎(chǔ)設(shè)施帶來了過重負(fù)擔(dān),這反過來又很可能會(huì)導(dǎo)致糟糕的用戶體驗(yàn)(UX)。例如,圖像處理需要大量的 CPU。如果 CPU 的負(fù)載變得非常高,這將會(huì)導(dǎo)致應(yīng)用其他處理資源的餓死現(xiàn)象。這會(huì)影響系統(tǒng)的延遲。而且,如果更糟糕的話,那么這會(huì)影響系統(tǒng)的可用性。
另一方面,人的問題 與應(yīng)用的關(guān)系并不大,它關(guān)系到你會(huì)如何組織團(tuán)隊(duì)。在應(yīng)用程序的特定部分,投入工作的人越多,開發(fā)和部署就會(huì)越慢,而且越容易出錯(cuò)。例如,如果你有 30 個(gè)工程師都在競(jìng)爭(zhēng)“持續(xù)部署(CD)”同一個(gè)服務(wù),就會(huì)出現(xiàn)很多排隊(duì)的現(xiàn)象,這意味著很多本可以交付產(chǎn)品的工程師只能坐等輪到他們進(jìn)行部署。
自 8 年前成立以來,InVision] 一直都是一個(gè)單體系統(tǒng),當(dāng)時(shí)只有3 個(gè)工程師。隨著公司的成長(zhǎng)和發(fā)展,系統(tǒng)的數(shù)量幾乎沒有增加,但是工程團(tuán)隊(duì)的規(guī)模卻在快速擴(kuò)張。幾年的時(shí)間,我們有了幾十名工程師,包括前端和后端,他們?cè)谕粋€(gè)代碼庫(kù)上開展工作,所有的部署都會(huì)到同一個(gè)服務(wù)隊(duì)列中。
如前文所述,大量的人在同一個(gè)地方工作會(huì)產(chǎn)生很大的問題。不僅各種團(tuán)隊(duì)會(huì)競(jìng)爭(zhēng)相同的部署資源,而且每當(dāng)遇到“緊急事件”的時(shí)候,多個(gè)團(tuán)隊(duì)的代碼都需要回滾。而且,在處理事件的時(shí)候,所有團(tuán)隊(duì)都不能進(jìn)行部署。可以想象,這會(huì)在整個(gè)組織造成很多摩擦,對(duì)工程團(tuán)隊(duì)和產(chǎn)品團(tuán)隊(duì)均是如此。
同時(shí),“微服務(wù)”的出現(xiàn)是解決“人的問題”的。一群選定的工程師圍繞他們認(rèn)為的與團(tuán)隊(duì)邊界相對(duì)應(yīng)的應(yīng)用組成部分開始劃分邊界。這樣做的目的是為了讓團(tuán)隊(duì)能更加獨(dú)立地工作,獨(dú)立地部署,從而發(fā)布更多產(chǎn)品。早期的 InVision 微服務(wù)幾乎與解決技術(shù)問題毫無關(guān)系。
如果你從事微服務(wù)的話,那么肯定聽說過“康威定律”,它是由 Melvin Conway 在 1967 年提出的:
任何設(shè)計(jì)系統(tǒng)(廣義定義)的組織,必然會(huì)產(chǎn)生以下設(shè)計(jì)結(jié)果:即其系統(tǒng)的結(jié)構(gòu)就是該組織溝通結(jié)構(gòu)的寫照。
該定律通常以“編譯器”為樣例進(jìn)行說明:
如果有四個(gè)組在從事一個(gè)編譯器相關(guān)的工作,那么這個(gè)編譯器肯定是要分四個(gè)步驟的。
這里的觀點(diǎn)在于,解決方案是圍繞團(tuán)隊(duì)結(jié)構(gòu)(和團(tuán)隊(duì)通信開銷)進(jìn)行“優(yōu)化”的,而不一定是為了解決特定的技術(shù)或性能問題。
在微服務(wù)出現(xiàn)之前,康威定律一般都是以負(fù)面的角度來進(jìn)行討論的。比如,康威定律代表著你的應(yīng)用規(guī)劃和組織比較糟糕。但是,在后微服務(wù)時(shí)代,康威定律有了更多的維度。因?yàn)槭聦?shí)證明,如果你能將系統(tǒng)分解為一組具有 內(nèi)聚邊界 的 獨(dú)立服務(wù),那么就能以更少的 bug 發(fā)布產(chǎn)品,因?yàn)槟闼鶆?chuàng)建的團(tuán)隊(duì)更專注于一組服務(wù),而這些服務(wù)具備更窄小的職責(zé)范圍。
當(dāng)然,康威定律的收益在很大程度上依賴于在哪里劃分邊界以及這些邊界 隨時(shí)間的推移該如何變化。這也就是我和我的 Rainbow 團(tuán)隊(duì)的職責(zé)所在。
多年來,InVision 必須要從組織和基礎(chǔ)設(shè)施方面進(jìn)行發(fā)展。這意味著,在其背后,有一個(gè)較老的“遺留”平臺(tái)和一個(gè)不斷發(fā)展的“現(xiàn)代”平臺(tái)。隨著越來越多的團(tuán)隊(duì)遷移至“現(xiàn)代”平臺(tái),這些團(tuán)隊(duì)之前負(fù)責(zé)的服務(wù)則要移交給剩下的“遺留”團(tuán)隊(duì)。
如今,我的團(tuán)隊(duì)就是遺留團(tuán)隊(duì)。這個(gè)團(tuán)隊(duì)已經(jīng)緩慢,但穩(wěn)定地負(fù)責(zé)越來越多的服務(wù)。這意味著:人數(shù)變少了,但是代碼倉(cāng)庫(kù)變多了,編程語(yǔ)言變多了,數(shù)據(jù)庫(kù)變多了,監(jiān)控儀表盤變多了,錯(cuò)誤日志變多了。
簡(jiǎn)而言之,康威定律為組織帶來的所有收益,隨著時(shí)間的推移,都變成“遺留”團(tuán)隊(duì)的負(fù)債。所以,我們一直在努力“調(diào)整”責(zé)任域,讓平衡回歸康威定律。或者,換句話說,我們?cè)趪L試改變服務(wù)邊界以匹配團(tuán)隊(duì)的邊界。這意味著,將微服務(wù)重新合并為單體架構(gòu)。
也許,微服務(wù)架構(gòu)最糟糕的事情就是用了“微”這個(gè)字。“微”是一個(gè)毫無意義,但具有沉重負(fù)擔(dān)的術(shù)語(yǔ),它實(shí)際上代表了歷史原因和人們的偏見。更合適的術(shù)語(yǔ)應(yīng)該是“合適的大小”。微服務(wù)的目的從來不是成為“小的服務(wù)”,而是成為“大小合適”的服務(wù)。
“微”這個(gè)術(shù)語(yǔ)毫無意義,不代表任何實(shí)際的內(nèi)容。而“合適的大小”意味著服務(wù)經(jīng)過了 恰當(dāng)?shù)卦O(shè)計(jì),以滿足其需求:它負(fù)責(zé)“合適數(shù)量”的功能。而且,至于什么是“合適”并不是一個(gè)靜態(tài)的概念,它取決于團(tuán)隊(duì),即團(tuán)隊(duì)的技能集、組織的狀態(tài)、投資回報(bào)率(return-on-investment,ROI)的計(jì)算、持有成本以及該服務(wù)運(yùn)行的時(shí)間點(diǎn)。
對(duì)我的團(tuán)隊(duì)來說,“合適的大小”意味著更少的代碼倉(cāng)庫(kù),更少的部署隊(duì)列,更少的語(yǔ)言以及更少的運(yùn)維儀表盤。對(duì)于這個(gè)非常小的團(tuán)隊(duì)來說,“合適的大小”更多的是關(guān)于“人”,而不是關(guān)于“技術(shù)”。所以,就像 InVision 最初引入微服務(wù)是解決“人的問題”一樣,我們團(tuán)隊(duì)現(xiàn)在摧毀這些微服務(wù)也是為了解決“人的問題”。
姿態(tài)是一樣的,只是表現(xiàn)形式有所不同。
我為團(tuán)隊(duì)在遺留平臺(tái)上所付出的努力而感到自豪。雖然團(tuán)隊(duì)規(guī)模不大,但是我們利用自己所擁有的東西完成了很多的工作。我把這種成功歸功于我們對(duì)遺留平臺(tái)的深入了解,積極的實(shí)用主義,以及不斷努力設(shè)計(jì)一個(gè)能對(duì)應(yīng)我們能力的系統(tǒng),而不是試圖擴(kuò)大我們的能力以滿足系統(tǒng)需求。這可能聽起來很狹隘,但是,這是我們團(tuán)隊(duì)及其所擁有的資源在這個(gè)時(shí)刻唯一可行的方法。
支撐創(chuàng)建獨(dú)立服務(wù)的論據(jù)之一就是這些服務(wù)是可以“獨(dú)立擴(kuò)展”的。也就是說,可以更有針對(duì)性地提供服務(wù)器和數(shù)據(jù)庫(kù),以滿足服務(wù)的需求。因此,與其創(chuàng)建大型的服務(wù)卻只擴(kuò)展其中一部分功能,我們能夠在獨(dú)立擴(kuò)展其他服務(wù)的同時(shí),讓某些服務(wù)保持規(guī)模很小的狀態(tài)。
在所有關(guān)于為什么說獨(dú)立服務(wù)是一件“好事”的理由中,這個(gè)理由經(jīng)常被提及,但是在我(有限的經(jīng)驗(yàn))看來,這通常是不成立的。除非某項(xiàng)功能是 CPU 密集、IO 密集 或 內(nèi)存密集 的,否則獨(dú)立的可擴(kuò)展性可能并不是你需要擔(dān)心的“能力”。很多時(shí)候,你的服務(wù)器都在等著做事情,為一個(gè)應(yīng)用程序添加“更多的 HTTP 路由處理程序”并不會(huì)突然耗盡它所有的資源。
如果我能回到過去,重新嘗試我們的微服務(wù),我 100% 會(huì)先關(guān)注所有 “CPU 密集”的功能:圖像處理和調(diào)整大小、縮略圖生成、PDF 導(dǎo)出、PDF 導(dǎo)入、使用rdiff的文件版本管理、ZIP 壓縮文件生成。
我會(huì)沿著這些邊界組織團(tuán)隊(duì),讓他們創(chuàng)建“純的”服務(wù),只處理輸入和輸出(即,沒有“集成數(shù)據(jù)庫(kù)”,也沒有“共享文件系統(tǒng)”),這樣其他所有的服務(wù)都可以使用它們,同時(shí)保持了松耦合。
我并不是說這樣就能解決我們所有的問題 -- 畢竟我們的“人的問題”比 “技術(shù)的問題”要多。但是,它可以解決一些“合適性”的問題,從長(zhǎng)遠(yuǎn)來看,這可能會(huì)讓生活變得更輕松一些。
服務(wù)并不是在抽象地運(yùn)行:它們要在服務(wù)器上運(yùn)行,與數(shù)據(jù)庫(kù)通信,報(bào)告度量指標(biāo)并且還會(huì)生成日志條目。所有的這些都需要真正的經(jīng)濟(jì)成本。所以,盡管“l(fā)ambda 函數(shù)”在我們不使用它們的時(shí)候,不會(huì)花掉我們的錢,但是大多數(shù)“微服務(wù)”肯定還是會(huì)花錢的。特別是當(dāng)我們?yōu)榱藙?chuàng)建一個(gè)“高可用”的系統(tǒng)而需要維護(hù)冗余的時(shí)候。
我的團(tuán)隊(duì)將微服務(wù)重新合并成單體架構(gòu)對(duì)業(yè)務(wù)帶來了切實(shí)的經(jīng)濟(jì)影響(這種影響是正面的)。這種影響并不巨大,我們只是在談?wù)撘恍┬⌒偷姆?wù),但也不是微乎其微。所以,在將系統(tǒng)合并之后,我們不僅得到了“人”的方面的收益,還得到了實(shí)際的經(jīng)濟(jì)收益。
原文鏈接:https://www.bennadel.com/blog/3944-why-ive-been-merging-microservices-back-into-the-monolith-at-invision.htm
