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