“微服務(wù)并不能解決你的爛代碼問題
很久以來,軟件的交付質(zhì)量一直是一個大家比較關(guān)心的問題,而程序員和架構(gòu)師也一直在極力尋找一種更好的方式來構(gòu)建應(yīng)用系統(tǒng)。隨著互聯(lián)網(wǎng)爆炸式的增長,對于系統(tǒng)的交付速度和質(zhì)量的要求也日漸提高,這不僅對程序員寫的程序,而且對架構(gòu)師對整個系統(tǒng)的架構(gòu)能力提出了更高的要求。如果你學(xué)過領(lǐng)域驅(qū)動設(shè)計,你會知道系統(tǒng)的構(gòu)建應(yīng)該建立在業(yè)務(wù)模型之上,而不是圍繞著數(shù)據(jù)庫的表,視圖,存儲過程。如果你學(xué)過系統(tǒng)設(shè)計的
六邊形
理論,你同樣也會知道提煉
業(yè)務(wù)核心
模型才是構(gòu)建一個具有可擴展性系統(tǒng)的重心所在。如果你了解過CI/CD,從客戶的滿意度來說,持續(xù)交付要比瀑布模型交付好太多。
image
image
image再加上非功能性的一些需求,最典型的:系統(tǒng)的高可用,高擴展性,高性能。這一系列要求對于傳統(tǒng)的開發(fā)模式根本不可能滿足。伴隨著容器技術(shù),基礎(chǔ)設(shè)施自動化,大型集群的流行,微服務(wù)也慢慢的浮出水面。它并不是被發(fā)明出來的,而是隨著軟件系統(tǒng)的不斷發(fā)展衍生出來的。最重要的是很多公司在采用了微服務(wù)的架構(gòu)之后確實明顯改善了軟件系統(tǒng)的交付速度和質(zhì)量,并且可以有更多的機會去嘗試新的技術(shù),比如現(xiàn)在流行的
容器技術(shù),云原生,Serverless
等。在團隊與團隊之間,職責(zé)更加清晰明顯,而且不同技術(shù)棧的團隊也可以很融洽的進行合作。
“當(dāng)然,我比較排斥那種為了效仿而進行的技術(shù)改革。每個公司都有自己的技術(shù)沉淀以及債務(wù),不要妄圖利用一種完美的技術(shù)來填平所有的焦油坑。
微服務(wù)
到目前為止,網(wǎng)絡(luò)上關(guān)于微服務(wù)的定義有很多版本,無論什么樣的文字定義都始終圍繞著以下核心:
“微服務(wù)是一組小而自治并且能協(xié)同工作的系統(tǒng)服務(wù)。它不僅僅是代碼級別的重用,更重要的是業(yè)務(wù)級別的重用和自治。
這讓我不禁想到了“中臺”的定義,中臺其中一個很明顯的目標(biāo)是要達到
公司業(yè)務(wù)級別
的重用,進而反饋給業(yè)務(wù)一些結(jié)果來達到閉環(huán)效果。
image微服務(wù)一定要足夠小嗎?
每一個系統(tǒng),在誕生的時候其實都很小,隨著產(chǎn)品的不斷發(fā)展,才會賦予這個系統(tǒng)更多的職能,但是,這個系統(tǒng)最主要的特點仍然是:一個
單體應(yīng)用
。什么叫單體應(yīng)用?說白了,所有的代碼都在一個工程中,對外輸出的也只有一個工程。每次修改任何一個功能,哪怕是修改一個字符,都需要重新發(fā)布。隨著時間的推移,當(dāng)這個單體越來越大的時候,你會發(fā)現(xiàn)大量的重復(fù)性代碼,大量的重復(fù)性功能,甚至?xí)嬖诖罅康闹貜?fù)性SQL語句。這些還只是表面現(xiàn)象,如果想要修改一個功能,居然會意想不到的影響很多地方,隨著人員的離職等情況,這些代碼沒有人會熟悉,慢慢的傳說中的“屎山”出現(xiàn)了。
image如果有一個技術(shù)且職責(zé)比較上心的技術(shù)經(jīng)理或者總監(jiān),一些單體應(yīng)用至少還會根據(jù)不同的模塊進行抽象,用接口的方式來達到代碼內(nèi)的職責(zé)分離和高內(nèi)聚。這里多說一句:
高內(nèi)聚,松耦合
在設(shè)計任何系統(tǒng)的時候都非常重要,尤其在大的單體系統(tǒng)應(yīng)用中。
“把因為相同原因而變化的模塊(代碼)劃分到一起,而把不同原因而變化的模塊(代碼)分離出來
高內(nèi)聚松耦合可以說在微服務(wù)中體現(xiàn)的淋漓盡致,因為微服務(wù)就是按照業(yè)務(wù)的不同模塊來進行劃分的,微服務(wù)之間擁有
明確的業(yè)務(wù)邊界
,某個功能屬于哪個微服務(wù),應(yīng)該寫在哪個微服務(wù)里,一目了然。至于微服務(wù)的劃分粒度,說實話,業(yè)界并沒有一個明確的標(biāo)準。但是服務(wù)之間的
邊界是明確的
,假如說:一個微服務(wù)內(nèi)還存在多個小模塊,這些小模塊是否也應(yīng)該劃分為更小的微服務(wù)呢?這本質(zhì)上還是微服務(wù)粒度劃分的問題,也是一個沒有明確答案的問題,不過卻可以依據(jù)一下幾個準則去進行微服務(wù)的規(guī)劃:
- 模塊的大小。如果一個模塊可以在兩周之內(nèi)進行重寫,那這個模塊完全可以獨立成微服務(wù)。
- 模塊是否存在獨立的變化。如果一個模塊會頻繁變化,可以考慮獨立成一個單獨的微服務(wù)。
- 模塊是否具有比較高的性能需求。如果一個模塊在性能這個指標(biāo)上有比較高的要求,為了應(yīng)對這種要求可以劃分為獨立的微服務(wù)。
- 雖然每個人對小都沒有明確的概念,但是對“大”卻有著明確的敏感性。當(dāng)你感覺一個系統(tǒng)“大”的時候,就可以考慮進行拆分了
“警告:系統(tǒng)進行微服務(wù)的拆分,并非是越小越好,更多的時候在拆分的時候要根據(jù)團隊,運維能力等進行綜合考慮,在總量不變的情況下,小意味著數(shù)量多,數(shù)量多意味著必須要投入更多的人力物力去管理運維,并且也會引入分布式下的很多問題。這個之后咱們具體詳聊.....
微服務(wù)優(yōu)勢明顯嗎?
到目前為止,全網(wǎng)都在吹噓進行微服務(wù)的劃分,但是在脫離具體業(yè)務(wù)場景的條件下,大力倡導(dǎo)拆分微服務(wù),這很明顯就是在教人耍流氓而不負責(zé)任。我某天看到一篇文章返璞歸真的要回歸單體應(yīng)用,我看完之后默默的點了個贊,從文章中具體的業(yè)務(wù)來說,確實采用單體應(yīng)用比微服務(wù)更合適,因為他們的業(yè)務(wù)邊界很模糊,可以說沒有業(yè)務(wù)邊界,一味的進行微服務(wù)劃分,帶來的是一系列的
分布式問題
,對于公司而言反而沒有益處。說到微服務(wù)的優(yōu)勢,一般都是對比單體服務(wù)來說的,單體應(yīng)用有哪些缺點呢?
- 開發(fā)效率低:所有的開發(fā)在一個項目改代碼,遞交代碼相互等待,代碼沖突不斷
- 代碼維護難:代碼功能耦合在一起,新人不知道何從下手
- 部署不靈活:構(gòu)建時間長,任何小修改必須重新構(gòu)建整個項目,這個過程往往很長
- 穩(wěn)定性不高:一個微不足道的小問題,可以導(dǎo)致整個應(yīng)用掛掉
- 擴展性不夠:無法滿足高并發(fā)情況下的業(yè)務(wù)需求
這些你都可以用百度搜到,這里不再詳細展開了。微服務(wù)的優(yōu)勢明顯嗎?我想說,對于很多
大型系統(tǒng)
確實很奏效,但是對于一些中小型系統(tǒng),那就不一定了。
“就像很多架構(gòu)師吹噓的充血模型一樣,一味的貶低貧血模型一無是處,無形中總是在拉低自己的格局。
高擴展性
當(dāng)系統(tǒng)處于單體系統(tǒng)的時候,如果某一個模塊遇到性能問題或者想要保證高可用特性,只能將整個系統(tǒng)進行多份部署來達到目的,哪怕是只有一個小小的部分存在性能問題。如果把這一部分進行了微服務(wù)的拆分,那么就可以只針對這個微服務(wù)進行擴展了,無論是性能還是高可用的要求,都可以單獨進行,而不必影響其他模塊,而且公司對于成本問題上要低很多。舉一個簡單例子:假如有一個電商系統(tǒng),包含了商品,訂單,支付等模塊,對于性能而言,用戶瀏覽商品量要比下訂單量大很多,很顯然,商品模塊對于性能有著更高的要求,這個時候就可以考慮把商品這個模塊獨立出來,以便提供橫向擴展的高性能能力。
彈性
在傳統(tǒng)的單體系統(tǒng)中,當(dāng)服務(wù)不可用的時候,就意味著所有的模塊都不可用,雖然也可以通過部署多份大單體的方式來降低這個概率,但是這種方式始終是種詬病。在微服務(wù)架構(gòu)中,如果一個服務(wù)不可用,并不會影響全部的服務(wù),當(dāng)然如果做好了微服務(wù)的降級,限流等工作,將會把影響降低到最低。
部署簡單
在大單體時代,哪怕是修改了一行代碼也需要重新編譯整個項目來進行重新部署,這種部署方式其實隱含的風(fēng)險非常大,所以很多大單體的運維人員都不會頻繁進行項目的部署,而且部署的時候很多時候要準備好通宵(因為風(fēng)險大),尤其是那種多個迭代的大部署行為。在微服務(wù)的架構(gòu)下,每個微服務(wù)都是獨立部署的,這樣就可以針對迭代進行更快的上線操作,而不影響其他服務(wù),而且就算是線上出問題,回滾操作也非???。能夠快速的迭代新功能意味著用戶可以快速的嘗試新功能,這在我們交付高質(zhì)量的軟件是非常有利的。
技術(shù)自由
由于每個微服務(wù)之間交互都采用RPC或者REST進行交互,而這些交互方式又有著嚴格的規(guī)范,所以每個微服務(wù)采用什么技術(shù)棧是相對自由的,不同團隊之間技術(shù)的差異性在微服務(wù)架構(gòu)下不復(fù)存在,而且每個團隊都可以嘗試一些新技術(shù),最重要的是每個微服務(wù)都可以根據(jù)自身的業(yè)務(wù)特點來進行合適的技術(shù)選型,比如:當(dāng)一個典型的文檔存儲微服務(wù),我們可以選擇采用mongoDB來做存儲;當(dāng)一個搜索型微服務(wù),我們可以采用ES來做存儲。
image程序員的福音
在大單體的時代,時常會發(fā)生“我的代碼被哪個孫子改了”的情況,由于大家都在一個大的代碼庫進行工作,還會偶爾發(fā)生代碼互相覆蓋的情況(我想很多人都發(fā)生過這種情況)。而在微服務(wù)的架構(gòu)下,每個劃分出來的微服務(wù)都有自己的獨立
代碼倉庫
,最重要的一點這個代碼倉庫只有一個團隊在使用,至于團隊內(nèi)的溝通要比團隊之間溝通暢快的多,所以代碼管理這部分幾乎不會出現(xiàn)什么問題。同一個業(yè)務(wù)的功能,只需要開發(fā)一遍,至于使用端是網(wǎng)頁,還是桌面,還是小程序或者app,都可以重用一套接口,真正的實現(xiàn)了業(yè)務(wù)上的重用。這才是程序員想要的結(jié)果?。。。?!而且對于某個微服務(wù)的重構(gòu)工作會非常順利,因為每個微服務(wù)的
代碼量不會很大,而且業(yè)務(wù)也很清晰,這在大單體時代是不存在的。
總結(jié)
就像“人月神話”中描述的一樣,微服務(wù)也并非銀彈。如果一個架構(gòu)師盲目的進行微服務(wù)的拆分會面臨著分布式系統(tǒng)的一系列的問題,比如:網(wǎng)絡(luò)的不可靠性帶來的問題,分布式事務(wù)帶來的一致性問題,分布式監(jiān)控的問題,還有最重要的CAP抉擇問題等。所以:
“微服務(wù)有時候可能并不適合你,誰用誰知道?。?!