先講一個(gè)關(guān)于微服務(wù)的小故事:第一次接觸到微服務(wù)這個(gè)概念的時(shí)候,我的第一反應(yīng)以為微服務(wù)就是微信提供的某種服務(wù)焰薄。那段時(shí)間正是微信生態(tài)開始爆炸繁衍的時(shí)候,全中國(guó)好像把微信當(dāng)成了和上世界90年代一樣的下海年代扒袖,各種諸如微商塞茅,微店,微社區(qū)之類的微X概念盛行季率。不過自從稍微對(duì)這個(gè)名詞進(jìn)行了研究以后野瘦,我就再也不信任自己大腦的第一反應(yīng)了。人類大腦在認(rèn)知新概念的時(shí)候都會(huì)優(yōu)先采用偷懶模式飒泻,首先嘗試用一些已知的概念進(jìn)行連接鞭光,發(fā)現(xiàn)已知概念都無法連接以后才會(huì)去建立一個(gè)新的概念出來。我們都需要警惕這個(gè)認(rèn)知陷阱泞遗。
有哪些是微服務(wù)的誤解惰许?
總所周知,微服務(wù)這個(gè)概念是Martin Fowler大叔和James Lewis在2014年提出來的(https://martinfowler.com/articles/microservices.html)史辙,而大叔又是我們ThoughtWorks的“Chief Scientist”汹买,所以這幾年我們?cè)谌虻奈⒎?wù)相關(guān)業(yè)務(wù)一直保持迅猛增長(zhǎng)的勢(shì)頭佩伤,感覺可以堪比山東藍(lán)翔的挖掘機(jī)技術(shù)了。
這幾年卦睹,不論是大小的傳統(tǒng)銀行畦戒,還是某個(gè)制造業(yè)龍頭,甚至連一些政府機(jī)構(gòu)都找到我們說:我們的核心系統(tǒng)要進(jìn)行變成微服務(wù)的结序,我們的ERP要進(jìn)行微服務(wù)改造障斋,我們要做一個(gè)數(shù)字化的微服務(wù)平臺(tái)。當(dāng)我們進(jìn)一步詢問對(duì)方為什么要進(jìn)行微服務(wù)改造的時(shí)候徐鹤,有的客戶說是現(xiàn)在系統(tǒng)太大不好維護(hù)拆小了才好維護(hù)垃环,有的客戶說要學(xué)阿里搞數(shù)字化中臺(tái)。
如果讓這些客戶描述一下在他們心中什么才是微服務(wù)的時(shí)候返敬,下面是一些常見的回答:
- 業(yè)務(wù)方覺得遂庄,微服務(wù)就是有很多的小服務(wù)可以讓我調(diào)用,當(dāng)我要開展一個(gè)新業(yè)務(wù)的時(shí)候劲赠,可以很快地對(duì)這些服務(wù)進(jìn)行組裝涛目。
- 技術(shù)方覺得,微服務(wù)就是用Spring Boot框架構(gòu)建HTTP服務(wù)凛澎,要構(gòu)建輕量級(jí)的RESTful API霹肝,要使用API Gateway,要能夠做到服務(wù)的注冊(cè)和發(fā)現(xiàn)塑煎,微服務(wù)可以使用Docker容器運(yùn)行沫换,并且使用Kubernate進(jìn)行集群管理等等,好像只要使用了這些新技術(shù)就是微服務(wù)了最铁。
本人已經(jīng)在多個(gè)項(xiàng)目中進(jìn)行過微服務(wù)的設(shè)計(jì)和拆分讯赏,也最終能夠端到端地把設(shè)計(jì)的微服務(wù)最終落地實(shí)現(xiàn)出來。所以上面這些回答在我看來好像都少點(diǎn)什么冷尉。業(yè)務(wù)方想要的是能夠快速實(shí)現(xiàn)新需求漱挎,但是如果我把服務(wù)都做到一個(gè)單體里面,新需求也可以通過組裝服務(wù)接口來快速實(shí)現(xiàn)雀哨。技術(shù)方關(guān)注的是各種框架和技術(shù)磕谅,但是如果使用了這些框架和技術(shù)以后,隨著各種新需求的實(shí)現(xiàn)震束,“微服務(wù)”開始慢慢的膨脹起來怜庸,有一天你發(fā)現(xiàn)膨脹的“微服務(wù)”有一部分業(yè)務(wù)能力需要拆分出去,但這個(gè)服務(wù)內(nèi)部過度耦合的實(shí)現(xiàn)讓你已經(jīng)無從下手垢村,難道要再進(jìn)行一次微服務(wù)改造嗎割疾?
微服務(wù)的核心價(jià)值是什么?
讓我們先統(tǒng)一一下微服務(wù)定義嘉栓,全世界談到微服務(wù)的時(shí)候都在引用老馬的這個(gè)定義:“微服務(wù)是一種新的軟件架構(gòu)術(shù)語宏榕,微服務(wù)架構(gòu)描述的是通過一組可以獨(dú)立部署的服務(wù)來構(gòu)建軟件應(yīng)用的架構(gòu)拓诸。雖然沒有對(duì)此架構(gòu)體系的精確定義,但是有一些共同的特征:圍繞組織和業(yè)務(wù)能力麻昼,自動(dòng)化部署奠支,智能化的端點(diǎn),去中心化的編程語言和數(shù)據(jù)抚芦”睹眨“
在這個(gè)定義里其實(shí)并沒有給出微服務(wù)應(yīng)該使用什么技術(shù),也沒有說一個(gè)微服務(wù)應(yīng)該多大叉抡。微服務(wù)只是一種架構(gòu)風(fēng)格尔崔,這種價(jià)格風(fēng)格構(gòu)建出來的軟件可能具有哪些特征。既然是一種軟件架構(gòu)風(fēng)格褥民,而且我們都知道如果要構(gòu)建一個(gè)軟件應(yīng)用季春,采用10個(gè)微服務(wù)的架構(gòu)風(fēng)格來構(gòu)建,肯定要比采用一個(gè)服務(wù)來構(gòu)建的成本要高很多消返,因?yàn)槌讼嗤墓δ芤酝庠嘏⒎?wù)架構(gòu)還需要考慮服務(wù)之間如何進(jìn)行交互,如何保證安全等諸多問題撵颊。那為什么這些軟件行業(yè)的大師們要推崇這樣一種明顯增加開發(fā)成本的架構(gòu)方式呢宇攻?
關(guān)于這個(gè)問題,只要做過大型企業(yè)級(jí)軟件應(yīng)用開發(fā)的朋友們一定會(huì)直接想到答案秦驯。大型軟件應(yīng)用通常都有很長(zhǎng)的生命周期尺碰,在開始開發(fā)的時(shí)候采用傳統(tǒng)單體架構(gòu)也許會(huì)很快實(shí)現(xiàn)功能挣棕。但是會(huì)不斷地有新功能要被添加進(jìn)來译隘,隨著功能越來越多,軟件的復(fù)雜度會(huì)急劇上升洛心,修改bug或者增加一個(gè)新功能的成本越來越高固耘,甚至有一天會(huì)發(fā)生無法下手修改的情況。這個(gè)問題其實(shí)從有了軟件這個(gè)行業(yè)以來就一直困擾著軟件工程師們词身,他們也嘗試了很多種方法去解決這個(gè)問題厅目,有人從項(xiàng)目管理角度入手,認(rèn)為好的項(xiàng)目管理可以讓軟件更好維護(hù)法严;有人從工程實(shí)踐角度入手损敷,認(rèn)為采用各種敏捷方法可以讓軟件更好維護(hù)∩钇。可惜沒有一個(gè)是能夠徹底解決問題的銀彈拗馒。
微服務(wù)架構(gòu)風(fēng)格同樣也是為了解決軟件維護(hù)困難而被發(fā)明的,所以我希望所有正在正在進(jìn)行微服務(wù)改造或者準(zhǔn)備開發(fā)一個(gè)微服務(wù)軟件應(yīng)用的朋友們都能夠先明確我們要從微服務(wù)中獲得的最核心價(jià)值是什么:就是讓軟件系統(tǒng)在不停擴(kuò)張的同時(shí)卻沒有過度地增加軟件維護(hù)成本溯街∮展穑基于這個(gè)核心價(jià)值洋丐,使用什么技術(shù),使用什么語言挥等,有沒有用Docker友绝,拆分了多少個(gè)微服務(wù)等等這些都不是一個(gè)好的微服務(wù)軟件系統(tǒng)的核心訴求。
弄清楚了這個(gè)根本性問題肝劲,相信下一個(gè)問題已經(jīng)在你腦中浮現(xiàn)了:微服務(wù)架構(gòu)為什么能夠解決這個(gè)軟件系統(tǒng)難維護(hù)的問題呢迁客?對(duì)于這個(gè)問題一個(gè)比較簡(jiǎn)單直接的回答是因?yàn)橄到y(tǒng)被拆小了,拆分以后的微服務(wù)復(fù)雜度降低了辞槐,這樣修改也就容易了哲泊。但是仔細(xì)想想這跟答案也是有不充分的地方:
- 在拆分以后如果要修改一個(gè)功能發(fā)現(xiàn)有修改好多個(gè)微服務(wù),這不是變的更復(fù)雜更難維護(hù)了嗎催蝗?
- 拆分以后的一個(gè)微服務(wù)膨脹速度很快切威,那在這個(gè)微服務(wù)上是不是維護(hù)成本也會(huì)越來越高呢?
從這兩個(gè)追問我們可以發(fā)現(xiàn)丙号,拆成多少個(gè)微服務(wù)不是微服務(wù)架構(gòu)的要點(diǎn)先朦。如何保證拆出來的微服務(wù)容易維護(hù),而不又是一個(gè)小單體犬缨,這才是微服務(wù)架構(gòu)的要點(diǎn)和難點(diǎn)喳魏。很多客戶和行業(yè)內(nèi)的朋友在聊到微服務(wù)的時(shí)候也都提到,他們知道微服務(wù)架構(gòu)是好東西怀薛,但是對(duì)一個(gè)微服務(wù)應(yīng)該是怎么拆分和設(shè)計(jì)出來是完全沒有概念的刺彩。
所以,如何設(shè)計(jì)或拆分才能避免拆分出來的微服務(wù)不會(huì)只是一個(gè)拆小的小單體枝恋,這才是所有打算采用微服務(wù)架構(gòu)的組織最需要關(guān)注和解決的難點(diǎn)問題创倔。
如何拆才能避免小單體?
關(guān)于微服務(wù)拆分和設(shè)計(jì)焚碌,就不得不提到我司另外一位同事Newman的作品《微服務(wù)設(shè)計(jì)》畦攘,相信很多人都讀過這本書,這本書很薄十电,但是里面卻涉及到了關(guān)于微服務(wù)所有的的方面知押,服務(wù)建模,服務(wù)集成鹃骂,服務(wù)部署台盯,服務(wù)測(cè)試,服務(wù)監(jiān)控畏线,服務(wù)安全幾乎全部都囊括了静盅。但是美中不足是每一個(gè)問題都只是點(diǎn)到即止,如果作者能夠用一個(gè)構(gòu)建微服務(wù)的案例來串起來所有這些知識(shí)象踊,我相信這本書會(huì)更贏得更多的好評(píng)温亲。
在《微服務(wù)設(shè)計(jì)》的“第三章 如何建模服務(wù)”中棚壁,主要介紹的就是如何確定服務(wù)之間的邊界。Newman給出了兩個(gè)好服務(wù)的標(biāo)準(zhǔn):
低耦合:如果做到了服務(wù)之間的松耦合栈虚,那么修改一個(gè)服務(wù)就不需要修改另一個(gè)服務(wù)袖外。一個(gè)松耦合的服務(wù)應(yīng)該盡可能少地知道與之協(xié)作的那些服務(wù)的信息。
高內(nèi)聚:就是把相關(guān)的行為聚集在一起魂务,把不相關(guān)的行為放在別處曼验。如果你要修改某個(gè)服務(wù)的行為,最好只在一處修改粘姜。
這兩個(gè)標(biāo)準(zhǔn)是只要熟悉面向?qū)ο缶幊痰娜硕笺懹浻谛牡臉?biāo)準(zhǔn)鬓照,甚至是很多人經(jīng)常掛在嘴邊的。那么在微服務(wù)架構(gòu)中如何做才能滿足這兩個(gè)標(biāo)準(zhǔn)呢孤紧?Newman給出的方法是由Eric Evans提出的領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)(Domain Driven Design 下面簡(jiǎn)稱DDD)豺裆,DDD是Eric在2004提出的,早于微服務(wù)10年号显,所以從時(shí)間上可以看出DDD也不可能是為微服務(wù)準(zhǔn)備的臭猜。但是DDD的學(xué)習(xí)曲線過于陡峭對(duì)軟件工程師要求較高,大部分公司也已經(jīng)習(xí)慣了用簡(jiǎn)單的單體架構(gòu)來開發(fā)押蚤,所以DDD一直只是少部分高端軟件工程師的玩具蔑歌。而微服務(wù)架構(gòu)流行以后,大家發(fā)現(xiàn)使用DDD方法可以幫助設(shè)計(jì)出高內(nèi)聚低耦合的微服務(wù)揽碘,這樣DDD也成為了微服務(wù)設(shè)計(jì)的最佳實(shí)踐次屠。
客觀來說,從我接觸和實(shí)踐過的各種微服務(wù)拆分方法論中雳刺,DDD雖然不是唯一的劫灶,但是通過DDD建立的軟件架構(gòu)在實(shí)戰(zhàn)落地時(shí)能夠帶來的好處是非常明顯的。
舉一個(gè)具體項(xiàng)目的例子煞烫,在項(xiàng)目中我們使用DDD方法定義好了限界上下文(支付微服務(wù))浑此,以及上下文內(nèi)部的聚合累颂。所以在一個(gè)支付微服務(wù)中有支付聚合滞详,賬戶聚合,日志聚合紊馏,這些聚合時(shí)間通過消息訂閱方式進(jìn)行通信料饥。比如當(dāng)支付聚合提交支付經(jīng)辦以后,會(huì)向事件發(fā)布器發(fā)布一個(gè)支付已提交事件朱监,然后事件發(fā)布器會(huì)找到這個(gè)事件的兩個(gè)訂閱者賬戶聚合和日志聚合岸啡,賬戶聚合會(huì)根據(jù)事件保存支付的收款方信息,而日志聚合記錄一條提交支付的日志赫编⊙舱海可以明顯看到聚合之間通過事件實(shí)現(xiàn)了解耦奋隶,當(dāng)需要改動(dòng)一個(gè)聚合時(shí)并不會(huì)導(dǎo)致另外一個(gè)聚合的變動(dòng)。
隨著項(xiàng)目的進(jìn)行悦荒,很多微服務(wù)里面都有了日志聚合唯欣,然后我們發(fā)現(xiàn)好像應(yīng)該有一個(gè)微服務(wù)用來專門處理和日志相關(guān)的邏輯了。這時(shí)候基于上面的架構(gòu)搬味,我們可以很容易的把支付微服務(wù)中的賬戶聚合境氢,日志聚合抽離出去形成新的微服務(wù)。要知道這種基于聚合來拆分或合并微服務(wù)的動(dòng)作是在項(xiàng)目開發(fā)中經(jīng)常發(fā)生的事情碰纬,如果每次當(dāng)你需要從微服務(wù)中拆分一些模型和邏輯時(shí)候都發(fā)現(xiàn)這不是一個(gè)簡(jiǎn)單容易個(gè)過程萍聊,那么你需要停下來想想是不是又在構(gòu)建一個(gè)小單體了。
不要買櫝還珠
最后讓我再用另外一個(gè)故事來收尾吧悦析,在我最近參與的微服務(wù)設(shè)計(jì)改造項(xiàng)目中寿桨,客戶找了兩個(gè)咨詢公司來幫他們進(jìn)行微服務(wù)識(shí)別,我們采用的是DDD和事件風(fēng)暴工作坊的方法一步步推導(dǎo)出限界上下文强戴。最后客戶在比較了雙方的產(chǎn)出物后提出一個(gè)疑問牛隅,就是如果從識(shí)別了多少個(gè)微服務(wù)來看,兩個(gè)咨詢公司的結(jié)果好像沒有太大的差異酌泰?我覺得這種問題比較普遍媒佣,很多時(shí)候大家對(duì)微服務(wù)設(shè)計(jì)的理解都是以為只要最后確定拆分出多少個(gè)微服務(wù)就可以了。根據(jù)我這篇文章前面的論述相信你能夠明白陵刹,在進(jìn)行微服務(wù)設(shè)計(jì)之后默伍,最有價(jià)值的東西是設(shè)計(jì)出來的微服務(wù)當(dāng)業(yè)務(wù)的發(fā)展需要進(jìn)行拆分和重新組合時(shí),這個(gè)過程是非常輕松而且簡(jiǎn)單的衰琐。至于拆分出多少個(gè)微服務(wù)也糊,定義了多少個(gè)API這些比較顯而易見的度量指標(biāo)并不能給你帶來微服務(wù)架構(gòu)的真正價(jià)值,它們只是用來包裝珍珠的盒子而已羡宙。
在這篇文章中多次提到了DDD狸剃,限界上下文這些概念,由于篇幅限制這里沒有深入對(duì)這些概念進(jìn)行展開狗热。所以我在下面特別準(zhǔn)備了一些書單钞馁,在這些書中有更詳細(xì)的介紹。
- 《領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)》Eric Evan著匿刮,這本書非常有名僧凰,但是閱讀難度較大,有很多人表示這本書讀不懂熟丸,我自己前前后后至少讀了三遍以上训措,豆瓣地址https://book.douban.com/subject/1629512/
- 《實(shí)現(xiàn)領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)》Vaughn Vernon著,書比較厚,但是很落地绩鸣,有很多實(shí)際的例子來講解每個(gè)DDD的概念應(yīng)該如何應(yīng)用怀大,尤其是提出了領(lǐng)域事件這個(gè)模型作為DDD的一個(gè)充分補(bǔ)充 https://book.douban.com/subject/25844633/
- 《領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)模式、原理與實(shí)踐》 (Scott Millett) / Nick Tune著呀闻,這本書也是非常好的一本書叉寂,可惜市場(chǎng)上沒有新書買了,只能從淘寶上買高價(jià)書 https://book.douban.com/subject/26761413/