为什么Segment会从微服务退回单体架构?
近年來(lái),我們發(fā)布了很多文章介紹企業(yè)向微服務(wù)遷移的成敗經(jīng)驗(yàn)。最近,Segment的Alexandra Noonan寫(xiě)了一篇文章,講述了他們從單體架構(gòu)遷移到微服務(wù),之后又退回單體應(yīng)用的經(jīng)歷。文中Alexandra具體介紹了他們從原來(lái)的簡(jiǎn)單架構(gòu)遷移到微服務(wù)的過(guò)程:
\\\我們?cè)瓉?lái)有個(gè)API負(fù)責(zé)攔截事件并將它們轉(zhuǎn)發(fā)到一個(gè)分布式的消息隊(duì)列中。這里的一個(gè)事件指的是由網(wǎng)頁(yè)或移動(dòng)應(yīng)用生成的,包含用戶與用戶動(dòng)作信息的JSON對(duì)象。當(dāng)隊(duì)列中的事件被消費(fèi)后,系統(tǒng)會(huì)檢查用戶設(shè)置來(lái)決定接收事件的目標(biāo)。(……)之后事件被逐個(gè)發(fā)送到每個(gè)目標(biāo)的API。這樣的流程很合理,因?yàn)殚_(kāi)發(fā)者只需要將事件發(fā)送到Segment的API這一個(gè)目標(biāo)即可,無(wú)需創(chuàng)建幾十個(gè)集成。
\\\如果事件交付失敗,就會(huì)被系統(tǒng)重新加入隊(duì)列,也就是說(shuō)有時(shí)工作者進(jìn)程要一邊發(fā)送新的事件,一邊嘗試重新發(fā)送之前失敗的事件。這樣會(huì)導(dǎo)致所有目標(biāo)都出現(xiàn)延遲,Alexandra解釋說(shuō):
\\\為解決最緊迫的阻塞問(wèn)題,團(tuán)隊(duì)為每個(gè)目標(biāo)各創(chuàng)建了一個(gè)獨(dú)立的服務(wù)和隊(duì)列。這一新架構(gòu)包括一個(gè)新的路由進(jìn)程,它會(huì)接收入站事件并向每個(gè)選定的目標(biāo)分發(fā)一份該事件的拷貝。現(xiàn)在如果某個(gè)目標(biāo)出現(xiàn)問(wèn)題,只有它自己的隊(duì)列會(huì)回溯,不會(huì)影響其它目標(biāo)。這一微服務(wù)化的架構(gòu)將各個(gè)目標(biāo)獨(dú)立開(kāi)來(lái),這樣當(dāng)某個(gè)目標(biāo)又出現(xiàn)常遇到的問(wèn)題時(shí)就會(huì)非常有用。
\\\文章之后寫(xiě)到,Segment的開(kāi)發(fā)團(tuán)隊(duì)一開(kāi)始將所有代碼存放在一起,但這引發(fā)了許多問(wèn)題:
\\\最大的麻煩在于,只要一個(gè)測(cè)試崩潰,那么所有目標(biāo)的測(cè)試都會(huì)失敗。當(dāng)我們?cè)噲D部署一項(xiàng)改動(dòng)時(shí),我們必須先費(fèi)勁修復(fù)崩潰的測(cè)試,就算改動(dòng)與一開(kāi)始的變動(dòng)毫無(wú)關(guān)聯(lián)也得這樣做。為了解決這個(gè)問(wèn)題,我們決定將代碼拆分到每個(gè)目標(biāo)各自的存儲(chǔ)庫(kù)里。
\\\這樣一來(lái)開(kāi)發(fā)團(tuán)隊(duì)的靈活性的確改善了許多。然而隨著目標(biāo)數(shù)量的增加,存儲(chǔ)庫(kù)的數(shù)量也在同步增長(zhǎng)。為了讓開(kāi)發(fā)者免受維護(hù)這么多代碼庫(kù)的麻煩,Segment團(tuán)隊(duì)創(chuàng)建了許多共享庫(kù),存放所有目標(biāo)通用的變換和功能。這組共享庫(kù)大大減輕了他們維護(hù)工作的壓力。但這個(gè)措施也有不太容易發(fā)現(xiàn)的負(fù)面影響:向共享庫(kù)更新并測(cè)試改動(dòng)會(huì)花費(fèi)大量時(shí)間,還會(huì)增加破壞無(wú)關(guān)目標(biāo)的風(fēng)險(xiǎn)。最后這些庫(kù)開(kāi)始分裂為不同的版本,各自不統(tǒng)一,引發(fā)了之前沒(méi)有想到的一個(gè)問(wèn)題:每個(gè)目標(biāo)的代碼庫(kù)都會(huì)依賴不同版本的共享庫(kù)。Alexandra承認(rèn),他們當(dāng)時(shí)可以開(kāi)發(fā)工具來(lái)自動(dòng)將改動(dòng)更新到這些庫(kù)中,但那時(shí)他們又遇到了這個(gè)微服務(wù)架構(gòu)產(chǎn)生的一些新問(wèn)題。
\\\新出現(xiàn)的問(wèn)題是,每個(gè)服務(wù)都有自己的負(fù)載模式。有些服務(wù)一天處理幾個(gè)事件,有的服務(wù)每秒就能處理幾千個(gè)。如果目標(biāo)只處理很少的事件,工作者線程就得在出現(xiàn)負(fù)載問(wèn)題時(shí)手動(dòng)擴(kuò)展服務(wù)以滿足需求。
\\\他們的系統(tǒng)集成了自動(dòng)擴(kuò)展能力,但因?yàn)槊總€(gè)服務(wù)都需要指定CPU和內(nèi)存資源分配,調(diào)整自動(dòng)擴(kuò)展的設(shè)置“更像玄學(xué)而非科學(xué)”。如前所述,每次存儲(chǔ)庫(kù)的數(shù)量增長(zhǎng)時(shí)他們都要增加目標(biāo),最后團(tuán)隊(duì)平均每月要增加三個(gè)目標(biāo),當(dāng)然還要加上更多的隊(duì)列和服務(wù)。
\\\2017年初,Segment的一個(gè)產(chǎn)品的核心部分使我們達(dá)到了峰值負(fù)載。當(dāng)時(shí)的情況下我們好像在從微服務(wù)的大樹(shù)上摔下來(lái),一路撞上了所有的樹(shù)枝。我們這個(gè)小團(tuán)隊(duì)非但沒(méi)有提升效率,反而陷入了愈加復(fù)雜的泥潭。這個(gè)架構(gòu)的核心優(yōu)勢(shì)都成了負(fù)擔(dān)。我們的速度暴降,故障率卻在暴增。(……)于是,我們決定回退一步,重新考慮整個(gè)流程。
\\\文章最后Noonan回顧了他們?nèi)绾螖[脫這個(gè)微服務(wù)架構(gòu),其中他們還開(kāi)發(fā)了Centrifuge來(lái)替換所有獨(dú)立的隊(duì)列,將所有事件都發(fā)送到一個(gè)單體服務(wù)上。他們還將所有目標(biāo)的代碼都遷移到一個(gè)存儲(chǔ)庫(kù)里,不過(guò)這一次新增了一些代碼管理的規(guī)則:所有目標(biāo)都要使用同一個(gè)版本,每次更新時(shí)同步更替到新版本。他們?cè)僖膊挥貌傩母鱾€(gè)獨(dú)立版本之間的差異了,因?yàn)樗械哪繕?biāo)都在使用一個(gè)版本,以后也是如此。對(duì)于開(kāi)發(fā)者來(lái)說(shuō),管理越來(lái)越多的目標(biāo)所花費(fèi)的時(shí)間減少了,風(fēng)險(xiǎn)也降低了。
\\Noonan的文章還寫(xiě)了很多內(nèi)容,都是關(guān)于他們退回單體服務(wù)的經(jīng)歷。感興趣的讀者應(yīng)該去仔細(xì)讀一下,文章里面有很多架構(gòu)細(xì)節(jié)、關(guān)于存儲(chǔ)庫(kù)架構(gòu)的思考和建立彈性測(cè)試集的方法。最后,團(tuán)隊(duì)將回退的好處總結(jié)如下:
\\\2016年時(shí)我們還在使用微服務(wù)架構(gòu),我們?yōu)楣蚕韼?kù)帶來(lái)了32項(xiàng)改進(jìn)。而僅僅今年到現(xiàn)在我們就做出了46項(xiàng)改進(jìn)。過(guò)去半年來(lái)我們?yōu)閹?kù)帶來(lái)的改進(jìn)比2016年全年都多。因?yàn)樗械哪繕?biāo)都處于同一服務(wù)內(nèi),我們可以很好地搭配CPU密集型服務(wù)和內(nèi)存密集型服務(wù),所以擴(kuò)展服務(wù)以滿足性能需求變得非常容易。更大的工作者池能負(fù)載更多內(nèi)容,所以我們不再需要將處理少量負(fù)載的目標(biāo)掛起到頁(yè)面了。
\\\不過(guò)這個(gè)架構(gòu)回退過(guò)程也有一些負(fù)面影響,包括:隔離錯(cuò)誤變得更困難(一個(gè)目標(biāo)的錯(cuò)誤導(dǎo)致目標(biāo)崩潰,結(jié)果會(huì)傳染到所有目標(biāo));升級(jí)一個(gè)目標(biāo)的版本可能會(huì)破壞其它一些目標(biāo),于是后者也需要升級(jí)。Noonan在文章最后寫(xiě)下了誠(chéng)懇的總結(jié):
\\\在微服務(wù)和單體架構(gòu)之間做選擇時(shí),要注意它們各自都有自己需要考慮的因素。我們的架構(gòu)中有些部分是微服務(wù)表現(xiàn)更出色,但服務(wù)端的目標(biāo)遷移到微服務(wù)后的一系列麻煩是一個(gè)很好的教訓(xùn),證明這一流行趨勢(shì)在某些情況下能對(duì)生產(chǎn)力和性能有多大負(fù)面影響。結(jié)果對(duì)于我們來(lái)說(shuō),單體架構(gòu)才是最終解決方案。
\\\其實(shí)他們關(guān)于微服務(wù)的某些看法是很眼熟的。今年早些時(shí)候我們報(bào)道說(shuō),ThoughtWorks根據(jù)觀察認(rèn)為微服務(wù)尚未進(jìn)入普及周期。當(dāng)時(shí)的報(bào)道寫(xiě)到:“主要原因之一是很多組織并沒(méi)有為微服務(wù)做好準(zhǔn)備,他們?nèi)鄙僖恍╆P(guān)于運(yùn)營(yíng)和自動(dòng)化的基礎(chǔ)實(shí)踐”。此外,Jan在另一篇文章中總結(jié)了多年來(lái)微服務(wù)遷移的失敗案例。Berico科技的首席軟件工程師Richard Clayton提到了他們當(dāng)時(shí)遇到的一個(gè)問(wèn)題:
\\\在不同服務(wù)之間共享通用功能代碼,以消滅各個(gè)服務(wù)中的重復(fù)功能的努力卻帶來(lái)了巨大的負(fù)面影響,最終導(dǎo)致了大規(guī)模回退。
\\\回到原文,有很多關(guān)于這個(gè)話題的討論,比如Hacker News和Reddit上的這些;有些討論者認(rèn)為與微服務(wù)無(wú)關(guān)的一些因素可能導(dǎo)致了這些問(wèn)題。比如,有些評(píng)論指出Noonan的文章并沒(méi)有引用CI,只有CD,起碼這是一個(gè)奇怪的組合。還有評(píng)論認(rèn)為不止微服務(wù)會(huì)引發(fā)這些問(wèn)題,所有的分布式系統(tǒng)都是一個(gè)樣。關(guān)于這一點(diǎn)我們之前也提到過(guò),有人使用SOA時(shí)有過(guò)類(lèi)似的經(jīng)驗(yàn):
\\\我曾在一個(gè)類(lèi)似的代碼庫(kù)中工作過(guò),那時(shí)他們管它叫SOA,云還沒(méi)開(kāi)始流行。對(duì)服務(wù)的每次調(diào)用都會(huì)啟動(dòng)一個(gè)完整的服務(wù)實(shí)例。我想我們應(yīng)該強(qiáng)制將網(wǎng)絡(luò)延遲規(guī)定為架構(gòu)設(shè)計(jì)的要素之一。
\\\有趣的是很多討論串談到了微服務(wù)中數(shù)據(jù)上下文的問(wèn)題。這個(gè)話題我們探討過(guò)很多次,這也是微服務(wù)反對(duì)者的主要論據(jù)之一。HackerNews的一條評(píng)論舉例說(shuō):
\\\比這還糟呢。據(jù)我觀察多數(shù)微服務(wù)架構(gòu)根本就沒(méi)考慮一致性(“我們才不要亂七八糟的事務(wù)!”),盲目地隨大流還樂(lè)在其中。我搞不懂為啥子人們會(huì)覺(jué)得,把軟件模塊拆分開(kāi)來(lái)然后用緩慢不可靠的網(wǎng)絡(luò)和弱爆的手動(dòng)連接REST處理串起來(lái),就能神奇地讓架構(gòu)面目一新哩?我覺(jué)得人們產(chǎn)生這種生產(chǎn)力幻覺(jué)的原因是:”我把這些都搞定啦,現(xiàn)在我也有一套’管它是什么即服務(wù)‘的先進(jìn)玩意兒嘍!看看那酷斃的數(shù)據(jù)面板上閃爍的小綠燈吧,我們可是為了它干了好幾個(gè)月呢!“
\\\另外,為微服務(wù)定義域是多年來(lái)我們一直強(qiáng)調(diào)的微服務(wù)部署關(guān)鍵環(huán)節(jié)。有一篇PPT介紹了如何使用DDD解構(gòu)單體應(yīng)用,Reddit的一個(gè)討論串也談到了這一點(diǎn):
\\\建立一個(gè)出色的微服務(wù)架構(gòu)是很難的。我現(xiàn)在覺(jué)得關(guān)鍵在于恰當(dāng)?shù)胤指裟愕挠?#xff0c;當(dāng)系統(tǒng)進(jìn)化時(shí)持續(xù)關(guān)注這一層面。微服務(wù)并不像它的名字那樣,它不必非得那么小,但是要搭配適合這個(gè)架構(gòu)的元素。很多人的失敗正是因?yàn)楹鲆暳诉@一點(diǎn)。
\\\其他人怎么看?比如說(shuō),Segment的微服務(wù)架構(gòu)出現(xiàn)的問(wèn)題能否用其它方式解決,無(wú)需退回單體應(yīng)用?或者一開(kāi)始的單體架構(gòu)是否有辦法進(jìn)化得更好,解決原來(lái)的問(wèn)題,而無(wú)需切換到微服務(wù)?
\\查看英文原文:Why Segment Returned to a Monolith from Microservices? ?
\\感謝冬雨對(duì)本文的審校。
總結(jié)
以上是生活随笔為你收集整理的为什么Segment会从微服务退回单体架构?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 重定向输入输出
- 下一篇: 解决JBoss只能通过localhost