微服務(wù)是近期的熱點(diǎn)。
當(dāng)我在SoundCloud工作時,負(fù)責(zé)從一個巨大的Ruby on Rails應(yīng)用程序里遷移到眾多的微服務(wù)上。我已經(jīng)多次講述這個過程的技術(shù)問題了,在演講里,也在SoundCloud的工程師博客里寫了一系列文章。這些是工程師們最感興趣的話題,但是最近我才意識到從來沒有向大家解釋過我們最終使用微服務(wù)之前做了什么嘗試。
我很抱歉可能會讓一些技術(shù)人員失望,但是我們遷移到微服務(wù)更多的是跟生產(chǎn)力相關(guān),而不是單純的技術(shù)因素。下文會詳細(xì)解釋。
注意:本文有很多修正之處,為了使其更容易理解,將相當(dāng)混亂的一系列事件簡化成了線性的時間鏈。不過,我相信這很好得展示了在SoundCloud最初幾年所做的工作。
Next項目
當(dāng)我最初加入公司的時候,手頭最重要的項目內(nèi)部稱之為v2。該項目對我們的網(wǎng)站做徹底的改版,發(fā)布時的商標(biāo)名稱為The Next SoundCloud。
一開始我加入了后端團(tuán)隊,App團(tuán)隊。我們負(fù)責(zé)巨大的Ruby on Rails應(yīng)用程序。那時候還不稱其為遺留系統(tǒng),而稱之為mothership。App團(tuán)隊負(fù)責(zé)Rails應(yīng)用相關(guān)的所有事情,包括舊的用戶接口。Next是一個單頁面的JavaScript web應(yīng)用程序,我們遵照當(dāng)時的標(biāo)準(zhǔn)實踐,將其構(gòu)建為公開API的常規(guī)客戶端,用Rails monolith實現(xiàn)的。
App和Web這兩個團(tuán)隊是完全隔離的 -- 甚至在Berlin距離挺遠(yuǎn)的不同的大廈辦公。我們幾乎只在所有人都參加的大會上才能看到彼此,主要的溝通工具是問題跟蹤系統(tǒng)和IRC。如果你問任何一個團(tuán)隊的任何人我們的開發(fā)流程時如何工作的,他們可能會這么回答:
有人想到了某個功能,隨后寫了很多描述,并且畫了些模擬圖。
設(shè)計師優(yōu)化了用戶體驗。
編寫代碼。
一些測試之后,將應(yīng)用部署。
但有時候這個過程會遇到一些障礙。工程師和設(shè)計師都抱怨他們加班過多,但同時產(chǎn)品經(jīng)理和合作伙伴則抱怨他們永遠(yuǎn)無法按時得到想要的東西。
作為一個小型消費(fèi)者企業(yè),我們非常需要能夠確保吸引盡可能多的合作伙伴(就是那些Apple和Google在發(fā)布產(chǎn)品時在一頁P(yáng)PT里列出的合作伙伴),因為這些意味著免費(fèi)的宣傳和增長。我們也需要在圣誕節(jié)前發(fā)布Next的內(nèi)測版本,否則連續(xù)的假日就會將我們的所有計劃推延到新年的第二季度,因為我們不想在新網(wǎng)站上線之前推出任何新功能。要想能夠登上Keynote的PPT,并且確保我們不會浪費(fèi)整個季度,我們必須開始追逐截止日期。
就是這個時候,我們決定嘗試并且理解我們組織增長的流程到底是什么狀態(tài)。
流程hacking
在加入SoundCloud之前,我當(dāng)了好幾年的咨詢師,這些年里我學(xué)到的最有用的工具之一就是創(chuàng)建Value Stream Map的理念。我不想詳細(xì)講這個技術(shù)的為什么和如何做,但是如果你對下文講述的流程感興趣的話,至少已經(jīng)知道應(yīng)該搜索什么關(guān)鍵字了。
將不同工程師的非正式采訪融合在一起,并且從我們多個自動化系統(tǒng)里收集數(shù)據(jù),能夠畫出實際流程的圖,和我們認(rèn)為的流程作對比。我無法展示實際的文檔,但是實際圖和如下虛構(gòu)的圖差不多:
實際工作量類似:
有人想到一個功能。他們隨后編寫一個輕量級的spec,有一些模擬屏幕截圖,并且保存到Google Drive文檔里。
spec一直也就是個文檔,直到有人有時間真得實現(xiàn)它。
非常小的設(shè)計團(tuán)隊得到spec,并且為其設(shè)計用戶體驗。隨后會變成Web團(tuán)隊管理的Trello白板上的一個待辦事項。
這一待辦事項會在Trello白板上待上一段時間,最少是一個兩周的迭代之后,工程師才有時間查看它。
工程師可能開始基于這一項工作。在使用偽造/靜態(tài)數(shù)據(jù)將設(shè)計轉(zhuǎn)化成合適的基于瀏覽器的體驗之后,工程師會記錄下要想使這個功能能夠工作的話,Rails API所需的改動。這會進(jìn)入到Pivotal Tracker,App團(tuán)隊所選擇的工具。
這項待辦事項會一直呆在Pivotal里,直到App團(tuán)隊有人有時間查看它,通常又需要另一個兩周的迭代。
App團(tuán)隊成員可能為API能夠工作而開始編寫代碼,集成測試和任何所需的其他東西。隨后他們會更新Trello issue,讓W(xué)eb團(tuán)隊知道他們這部分工作已經(jīng)完成了。
更新過的Trello待辦事項會在backlog里待上一段時間,等待Web團(tuán)隊的工程師來完成他們之前開始的工作。
Web團(tuán)隊開發(fā)人員讓他們的客戶端代碼匹配上后臺實現(xiàn),并且發(fā)出可以部署的信號。
因為部署風(fēng)險很大,很慢并且很困難,App團(tuán)隊會等待好幾個功能都進(jìn)入主分支之后才一起部署到生產(chǎn)環(huán)境。這意味著功能可能會在源碼控制系統(tǒng)里待好幾天,并且你的功能很可能會因為完全不相關(guān)的代碼而被回滾。
某一天,這個功能終于部署到生產(chǎn)系統(tǒng)了。
這些步驟里很可能會有很多的來回,因為大家需要進(jìn)一步說明或者又有了更好的想法。不過暫時先忽略這些。
總之,一個功能需要花費(fèi)兩個月才能上線。更為糟糕的是:這個過程超過一半的時間都花在等待上,比如,一些Work In Progress的項目等待某個工程師來完成。
像上文所說的map這樣的工具使得更容易發(fā)現(xiàn)上述流程的詭異之處。我們只看圖就能想到的是必須為monolith采用release train的方式,而不是等到有足夠多的功能才一起部署,需要開始每天都進(jìn)行部署,而不用管有多少功能進(jìn)入了主分支。雖然這和持續(xù)部署還相差很遠(yuǎn),但是已經(jīng)可以幫助改進(jìn)一點(diǎn)我們的開發(fā)周期了:
低處的水果是行動的最大驅(qū)動力,但是我們的例子里最主要的問題顯然是前端和后端開發(fā)團(tuán)隊之間的來回。
在我們將工作分為Web和App團(tuán)隊時,其實就已經(jīng)將后端開發(fā)人員和實際的產(chǎn)品完全隔離開了。他們會感到沮喪,覺得自己對于產(chǎn)品完全沒有發(fā)言權(quán)。他們會覺得自己“只需要做像素抄寫員所告知的工作”。在一個比供應(yīng)鏈需要更多有經(jīng)驗的開發(fā)人員的市場里,這么對待團(tuán)隊似乎不是很好的做法。
但是如今需要關(guān)注的問題是花在開發(fā)上的47天里,只有11天真的在干事情。剩余的時間都在隊列里浪費(fèi)了,基本都是等待時間。
有一種說法認(rèn)為浪費(fèi)多少時間取決于等待新迭代的時間,但是即使改成迭代更短的流程,比如Kanban的variation,并沒能幫助多少。
我們隨后決定做一些有爭議的事情:將后端和前端開發(fā)人員配對,他們在某個功能完成之前對其負(fù)有完全的責(zé)任。我們只有8個后端工程師,11個前端工程師,所以該策略的爭論主要是因為需要前端開發(fā)人員盡可能早得完成大量工作,從而能讓后端開發(fā)人員在每個功能上只需花費(fèi)盡可能少的時間。這樣策略的啟動靠的是直覺,但是流程映射向我們展示了這樣的策略其實產(chǎn)生了反作用。即使不算足前端和后端開發(fā)人員的來回討論的時間,在東西實際上線之前,仍然有太長的等待時間。
我們決定首先單對嘗試,隨后再擴(kuò)大到其他人。新流程類似于:
每個人終于能將更多的時間花在每個功能的開發(fā)上。這其實不相關(guān),因為他們工作的同時,能夠在更少的時間內(nèi)完成端到端編碼。值得注意的是,即使后臺開發(fā)人員之前就和其他App團(tuán)隊的人比較遠(yuǎn),但是在改動進(jìn)入Rail應(yīng)用的主分支之前要求強(qiáng)制的代碼審核(也就是:Pull Request)流程。
時間減少了很多,我們決定在流程的其他步驟里嘗試并完成相同的事情。我們讓設(shè)計人員、產(chǎn)品經(jīng)理以及前端開發(fā)人員在某個功能的范圍內(nèi)緊密工作,周期時間更為縮短了:
的確有相當(dāng)可觀的時間縮減。更短的工作流,讓我們能夠更容易得在截止日期之前發(fā)布Next的第一個版本。我們持續(xù)以不同領(lǐng)域配對的方式來進(jìn)行迭代,最終導(dǎo)致功能團(tuán)隊構(gòu)造SoundCloud。但是這是以后要講的主題,這篇文章關(guān)注于這個長的Pull Request隊列里有什么東西。
[page]從mothership到遺留系統(tǒng)
讓我最為興奮的一件事情是所加入的SoundCloud有著濃厚的工程師文化。大部分聽上去和我用在ThoughtWorks項目里的方式類似,但是有一個方面是全新的:強(qiáng)制的代碼審核。
那時是2011年,所有的創(chuàng)業(yè)公司都在嘗試復(fù)制GitHub的模型,Zach Holman的GitHub如何使用GitHub來構(gòu)建GitHub演講里對此講述得非常清楚。在很多年使用和倡導(dǎo)基于trunk的開發(fā)模式后,我迫不及待得想看到SoundCloud這樣的公司以及GitHub能夠使用這一與眾不同的方式。
那時候,所有App團(tuán)隊的工程師都坐在一個桌子周圍,共享相同的任務(wù)backlog,并且互相非常親密。monolith的代碼基已經(jīng)很古老,成熟并且無聊了。我們在整個代碼基里都遵守相同的原則和模式,代碼提交都是基于現(xiàn)有設(shè)計,沒有什么意外情況。這使得Pull Request流程幾乎是一種儀式,大家花不到一個小時的時間審查提交的內(nèi)容。
因為越來越多的人離開了這個緊密的組織,在開發(fā)Next功能時去和Web團(tuán)隊的配對,正式的溝通渠道被破壞了。有問題的部署變得越來越頻繁,是由一些問題上的誤解所導(dǎo)致的,這些問題包括什么正在部署或者一些功能如何設(shè)計等。因為這通常是人為導(dǎo)致的,在很多這樣的問題之后,我們認(rèn)為方案必須要能夠在合并改動上強(qiáng)制實行一種更為嚴(yán)格的流程。從此以后,在將改動放到主分支并且最終部署之前,所有改變必須被第二個工程師“正式得”批準(zhǔn)。
如上圖所示,這導(dǎo)致了改動上線之前Pull Request的長時間等待。要想解決這個問題,我們檢查的第一步是確保每個人每天最少花費(fèi)一個小時來審核團(tuán)隊外部進(jìn)來的Pull Request -- 比如,從Next項目上工作的人。這并沒能更快得減少隊列的長度,最終我們意識到一些小的Pull Request被很多人審核,而一些大的Pull Request(Next的Pull Request通常很大)卻無人問津,直到產(chǎn)品經(jīng)理發(fā)怒為止。大改動的審核會花費(fèi)很多時間,基于我們的Rails代碼的特點(diǎn),也非常有風(fēng)險。大家都像躲開瘟疫一樣避開這些大型Pull Request。
我們一致決定從事Next功能開發(fā)的開發(fā)人員需要將其工作分解到更小、更好管理的Pull Request。這也和每個Pull Request都需要快速審核和合并的理念契合。但是同時將單一功能分解為多個小型Pull Request也會導(dǎo)致審核人員看不到整體情況:有時候一系列看上去都挺好的代碼提交實際上隱藏著危險的架構(gòu)錯誤。我們確定更好的用戶故事的需求,但是對員工進(jìn)行培訓(xùn)可能會花費(fèi)一些時間,為了業(yè)務(wù)需要,我們需要一個短期就能見效的方案。
最終應(yīng)用了書上的古老技巧:結(jié)對??闯鰜砹嗣?,我們的需求是代碼必須被另一個開發(fā)人員審核。使用結(jié)對編程之后,我們一直都在進(jìn)行實時的審核,這意味著每個代碼提交都能自動+1。大多數(shù)人都喜歡結(jié)對,不喜歡的人可以選擇保持單獨(dú)工作,但是只在和Next項目不相關(guān)的任務(wù)上。
我們開始嘗試了幾對,但是一件有意思的事情阻止了我們。我們發(fā)現(xiàn)monolithic的代碼基太大了,以至于沒有一個人了解所有的代碼。大家圍繞應(yīng)用程序的子模塊建立了自己的專業(yè)領(lǐng)域。當(dāng)一對人選擇了某個待辦事項,這對人可能發(fā)現(xiàn)自己沒有該部分代碼的足夠知識,因此他們不得不要么等待該領(lǐng)域的專家有空閑,要么和熟悉該領(lǐng)域的人重新配對,要么選擇另外的任務(wù),通常是低優(yōu)先級的任務(wù)。這兩種選擇都很糟糕。
這都成了公司的一個笑話,“這里的所有東西都很有趣,像做游戲一樣,直到你不得不學(xué)習(xí)monolith的時候。”
monolith無法減少的復(fù)雜度
要想從所花費(fèi)的時間里節(jié)省出這8天,我們需要后退一步,問問自己,為什么一開始需要這所有的Pull Request。隨著對自己的流程理解的深入,我們的想法隨之改變:
我們?yōu)槭裁葱枰狿ull Request?因為我們知道,基于多年的經(jīng)驗,大家通常會犯很低級的錯誤,這樣的改動上線后可能會導(dǎo)致整個平臺崩潰幾個小時。
為什么大家這么頻繁得犯錯?因為代碼基太復(fù)雜了。很難記住所有事情。
為什么代碼基這么復(fù)雜?因為SoundCloud從一個非常簡單的網(wǎng)站起步,但是隨著時間的演進(jìn),它發(fā)展成了一個大型平臺。我們擁有很多功能,各式各樣不同的客戶應(yīng)用程序、不同類型的用戶、同步和異步的工作流以及大型規(guī)模。代碼基實現(xiàn)并且反應(yīng)了如今復(fù)雜平臺的很多組件。
為什么我們需要單個代碼基來實現(xiàn)很多組件?因為范圍經(jīng)濟(jì)。mothership有著很好的部署流程和工具,架構(gòu)經(jīng)歷了尖峰性能和DDOS的實際考驗,也很容易水平擴(kuò)展等等。如果構(gòu)建新系統(tǒng),我們將必須為新系統(tǒng)構(gòu)建所有的這一切。
為什么我們在多個,或者小型系統(tǒng)里得不到規(guī)模經(jīng)濟(jì)?嗯。。。
第五個問題需要長篇大論來回答。我們自己的經(jīng)驗和同事的調(diào)研顯示可能有兩種方案:
(A)為什么我們在多個或者小型系統(tǒng)里得不到規(guī)模經(jīng)濟(jì)?問題不是我們不能,而是這樣做并不會比將所有東西放到一個代碼基里更為有效。相反,我們應(yīng)該圍繞monolith以及開發(fā)人員可用性來構(gòu)建更好的工具和測試。這也是Facebook和Etsy采用的方式。
(B)為什么我們在多個或者小型系統(tǒng)里得不到規(guī)模經(jīng)濟(jì)?我們可以。我們需要做一些實驗來找到所需的工具和支持。當(dāng)然,也取決于構(gòu)建了多少單獨(dú)的系統(tǒng),我們也需要思考規(guī)模經(jīng)濟(jì),但這是Netflix、Twitter等構(gòu)建系統(tǒng)的方式。
每種方案都有各自的支持者,并沒有哪一種明顯對或者錯。最大的問號是每個方案需要多少代價。金錢和資源不是問題,但是我們沒有足夠的人或時間來研究任何顛覆性的事情。我們需要一種能夠增量實現(xiàn)的策略,而且從一開始就能帶來價值。
我們從另外的角度審視擁有的東西。我們一直用非常簡單的格式來看待后臺系統(tǒng):
這樣的思路必然會將整個大盒子實現(xiàn)為一個單一的巨大代碼基。雖然我們在自我反省中發(fā)現(xiàn)了這一點(diǎn),但是實際事情并不像上圖那么明顯。
實際上,如果你打開這個大黑箱,會意識到我們的系統(tǒng)更像如下圖像所示:
我們沒有單一的網(wǎng)站,我們有的是擁有多個組件的平臺。每個組件都有自己的擁有者和stakeholder,以及獨(dú)立的生命周期。
比如,subscriptions模塊構(gòu)建了一次,只在支付網(wǎng)關(guān)要求我們在流程里改變什么的時候才需要改動。另一方面,notifications以及其他模塊,和增長以及留存率相關(guān)的,則會因為我們這個年輕的創(chuàng)業(yè)公司努力發(fā)展更多的用戶和內(nèi)容而每天都有改動。
它們還有不同服務(wù)級別的預(yù)期。一個小時沒有收到通知不會讓任何人抓狂,但是回放模塊五分鐘的中斷就會讓我們很受傷。
如果嘗試(A)方案,結(jié)論是要想使得monolith工作的唯一方式就是讓這些組件顯式化,不僅僅在代碼上,而且要從部署架構(gòu)上。
在代碼級別,需要確保單個功能的改動能夠在相對隔離的地方開發(fā),而不要求改動其他組件的代碼。需要確保該改動不會引入bug或者改變系統(tǒng)里其他不相關(guān)部分的運(yùn)行時行為。這是業(yè)界一直存在的問題,我們知道必須要讓隱式組件顯式化,并且確保充分了解了哪個模塊依賴于哪個模塊。
我們討論了使用Rails引擎和各種工具來實現(xiàn),類似如下:
在部署方面,需要確保某個功能能夠單獨(dú)部署。將某個模塊的改動推送到生產(chǎn)環(huán)境不要求非相關(guān)模塊的重新部署,并且如果這樣的部署失敗,導(dǎo)致生產(chǎn)環(huán)境被破壞,那么被影響的唯一功能就是有改動發(fā)生的功能。
要想實現(xiàn)這樣的系統(tǒng),我們考慮仍舊將相同的artifact部署到所有服務(wù)器上,但是使用負(fù)載均衡器來確保一組服務(wù)器只負(fù)責(zé)單一功能,將這個功能的問題和其他服務(wù)器上的功能隔離開:
要完成這些工作并不簡單。即使上述方案并不要求從一直使用的技術(shù)堆棧和工具隔離出去,這些改動還是會帶來了問題和風(fēng)險。
但是即使一切都很順利,我們也知道m(xù)onolith的現(xiàn)有代碼無論如何都需要重構(gòu)。這些代碼在過去幾年里一直帶來很多問題,到處都有欠下的技術(shù)賬。除了我們自己制造的麻煩,還需要從Rail 2.x升級到3,這本身也是個巨大的遷移工作。
這些問題都讓我們重新思考(B)方案。我們認(rèn)為它類似于:
但是至少我們能夠從開始的第一天就從這個方案受益。任何我們構(gòu)建的新東西都會是一個全新的項目,就不會再受Pull Request的困擾了。
我們決定試一試,并且最終將首個項目構(gòu)建成服務(wù),從monolith上隔離出來。該項目引入了多個大功能,并且重新思考了subscription模塊,并且比預(yù)先計劃提前了2組2個工程師完成。
體驗很棒,我們決定為新東西的構(gòu)建持續(xù)使用該架構(gòu)。我們的第一個服務(wù)使用Clojure和JRuby構(gòu)建,最終改為使用Scala和Finagle。
[page]必須引用康威定律
從2013年起SoundCloud所構(gòu)建的新東西幾乎都是服務(wù)。不知道從什么時候起,我們開始使用“微服務(wù)”來指代這些服務(wù),但是在一開始構(gòu)建這種架構(gòu)時并沒有想到這一點(diǎn)(SoundCloud在2013年在郵件里第一次使用單詞‘微服務(wù)’,2012年實現(xiàn)了第一個服務(wù))。
使用新架構(gòu)框架,我們能夠?qū)⑿鹿δ芩ㄙM(fèi)的時間減少到,雖然和最早的黃金時代比還有不少差距,但是對于一個在競爭異常激烈的音樂領(lǐng)域奮斗的公司而言已經(jīng)足夠好了:
到這里都很不錯,但是這是針對新功能的。無論何時需要改進(jìn)現(xiàn)有功能,這些都還在monolith里實現(xiàn),我們還是不得不回到舊的周期里。更糟糕的是,很多人在這些新微服務(wù)上比巨大代碼基上花費(fèi)更多的時間,因此空閑的審核員數(shù)目降低,但是Pull Request隊列持續(xù)增長。
每次一些大型改動出現(xiàn)的時候,我們都安排足夠的時間來確保從monolith里提取出舊系統(tǒng)。雖然這從來沒有發(fā)生過。大家仍然要么在舊代碼里實現(xiàn)這些改動,要么創(chuàng)建了一些詭異的混合代碼,改動在一個微服務(wù)里實現(xiàn),微服務(wù)和巨大代碼基耦合在一起。
這時,App“團(tuán)隊”更像是后臺開發(fā)人員的資源池,他們會和Web團(tuán)隊,設(shè)計師以及產(chǎn)品經(jīng)理配對,在某個功能上一起工作一段時間。大家會一直從一個功能跳到另一個功能,我們意識到我們并沒有為系統(tǒng)的任何部分指定所有者或者自主權(quán)。任何人如果覺得不為某件事情負(fù)責(zé),就都不會承擔(dān)風(fēng)險來研究這些歷史代碼。這正印證了古老的格言:所有人都承擔(dān)責(zé)任就等于沒有人承擔(dān)責(zé)任。
我們考慮將資源池分解成小型團(tuán)隊,關(guān)注于特定領(lǐng)域。在花費(fèi)很多時間嘗試找到正確的編組方式之、后,發(fā)現(xiàn)我們還是無法達(dá)成共識。這很讓人沮喪,有時候我只能將組分解成3-4人的小團(tuán)隊,幾乎隨機(jī)得指定他們的模塊職能。
這些團(tuán)隊被告知他們對所負(fù)責(zé)的模塊負(fù)全責(zé)。這意味著這些模塊造成中斷時會找到他們,同時他們也有自由去開發(fā)認(rèn)為合理的變化。如果他們決定將某些東西保留在monolith里,他們自己決定就好了。他們是維護(hù)代碼的人。
你可能會猜到,之后我們看到大量代碼脫離大型代碼基。Messages、stats以及新的iOS應(yīng)用所需的大部分改進(jìn)的功能都從主代碼基里抽離了出來。
一切都很順利,但是分解團(tuán)隊的半隨機(jī)的方式是很大的問題:單一團(tuán)隊負(fù)責(zé)生態(tài)系統(tǒng)里幾乎所有基礎(chǔ)功能和對象,類似跟蹤和用戶元數(shù)據(jù)和社交圖。該團(tuán)隊一直扮演救火隊的角色,無暇顧及遷移模塊到微服務(wù)上,因為這會帶來更多風(fēng)險和可能的中斷。
這個問題最近才解決了。我們?nèi)匀蛔寙我粓F(tuán)隊負(fù)責(zé)這些對象,但是現(xiàn)在的架構(gòu)更加穩(wěn)定,降低了需要救火的時間。最終讓這些人能夠有時間將項目本身從monolith里將模塊抽離出來。
如今,SoundCloud還有monolith,但是它的重要性每天都在降低。它仍然在很多功能的關(guān)鍵路徑上,但是由于strangler系統(tǒng),它甚至不再是面向互聯(lián)網(wǎng)的。我不確定最終是否會消失,其提供的一些功能很小并且很穩(wěn)定,保持這樣的狀態(tài)是最經(jīng)濟(jì)的,但是我們計劃一年時間里將monolith從任何關(guān)鍵路徑上移除。
未來
正如本文一開始所述,這是我們微服務(wù)探索的簡化版。
我在這個公司的最后12個月關(guān)注于我們想引入的范圍經(jīng)濟(jì)。就算我一直重復(fù)使用“微服務(wù)”的字眼也并不代表什么,可以確定的是如果有人使用該詞匯描述其架構(gòu),那么肯定有很多服務(wù)。隨著企業(yè)的發(fā)展,他們需要留意每個服務(wù)的固定花費(fèi)。
我的團(tuán)隊和我花費(fèi)了很多時間思考如何利用約束,并且確保該架構(gòu)的運(yùn)維不會比monolith更昂貴和復(fù)雜。期望一些工作能夠開源,因此一定要訂閱工程師博客哦。我在以后的博客里會繼續(xù)介紹更多內(nèi)容。
這些年我們學(xué)到了很多,即使我離開了SoundCloud,我也堅信這樣的架構(gòu)和團(tuán)隊組織(這些東西攜手并進(jìn))會在接下來的幾年里繼續(xù)幫助公司完成目標(biāo) -- 可能會一直到“無核”或者“納米服務(wù)”流行起來的時候。