怎樣的架構(gòu)才能配得上造到飛起的變化?
一、軟件復(fù)雜性
1、復(fù)雜原因
如果軟件系統(tǒng)存在持續(xù)的迭代周期,那么其中業(yè)務(wù)、技術(shù)、架構(gòu)的復(fù)雜性都會(huì)直線拉升,其相應(yīng)的開發(fā)難度也會(huì)提高,可以用一句話總結(jié)其根本原因:唯一不變的就是變化;
- 業(yè)務(wù)變化:導(dǎo)致復(fù)雜性的根本原因,在多端多版本適配的過程中代碼快速膨脹;
- 數(shù)據(jù)變化:數(shù)據(jù)隨著業(yè)務(wù)的變化和發(fā)展,不斷沉淀積累,需要做橫向與縱向的管理;
- 技術(shù)升級(jí):技術(shù)組件可能因?yàn)槁┒?,或者更好的解決問題,不間斷升級(jí)版本;
- 人員變動(dòng):模塊的開發(fā)人員一旦出現(xiàn)流動(dòng),換人接手會(huì)給代碼帶來風(fēng)格上的差異;
- 心態(tài)起伏:持續(xù)應(yīng)對(duì)復(fù)雜問題,但平穩(wěn)的心態(tài)很難持續(xù),也是人員流動(dòng)的一個(gè)因素;
應(yīng)對(duì)復(fù)雜的變化一直都是軟件工程的核心難點(diǎn)問題,如何用較小的架構(gòu)變化應(yīng)對(duì)較大的業(yè)務(wù)變化,就是設(shè)計(jì)中常說的:高內(nèi)聚、低耦合;還需要補(bǔ)充很重要的一點(diǎn):?jiǎn)螐募夹g(shù)層面是無法持續(xù)解決復(fù)雜問題的,還需要從管理角度去定義流程標(biāo)準(zhǔn),規(guī)范各種解決方案,是整個(gè)部門要持續(xù)面對(duì)的事項(xiàng)。
2、應(yīng)對(duì)復(fù)雜
不管是常說的設(shè)計(jì)模式、原則、面向?qū)ο螅€是架構(gòu)中常用的集群、微服務(wù)、領(lǐng)域驅(qū)動(dòng)等,都是在尋求更合理的方案來應(yīng)對(duì)業(yè)務(wù)的變化;但是沒有一勞永逸的解決方法,既要做一定前瞻性的設(shè)計(jì)去預(yù)期業(yè)務(wù),同時(shí)還要避免過度的設(shè)計(jì)影響業(yè)務(wù)進(jìn)度;這就需要研發(fā)團(tuán)隊(duì)具備一定的業(yè)務(wù)高度和技術(shù)深度:
在系統(tǒng)落地的過程中,需要對(duì)業(yè)務(wù)深入的分析和理解,不斷優(yōu)化技術(shù)層面的解決方案;比如微服務(wù)的思想是通過拆分的手段實(shí)現(xiàn)業(yè)務(wù)塊之間的低耦合,領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)則實(shí)現(xiàn)各個(gè)業(yè)務(wù)邏輯的高內(nèi)聚;下面圍繞兩種方式的實(shí)踐去詳細(xì)分析。
基于 Spring Boot + MyBatis Plus + Vue & Element 實(shí)現(xiàn)的后臺(tái)管理系統(tǒng) + 用戶小程序,支持 RBAC 動(dòng)態(tài)權(quán)限、多租戶、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能
- 項(xiàng)目地址:https://github.com/YunaiV/ruoyi-vue-pro
- 視頻教程:https://doc.iocoder.cn/video/
二、微服務(wù)架構(gòu)
1、架構(gòu)設(shè)計(jì)
系統(tǒng)的架構(gòu)設(shè)計(jì)是一件極度復(fù)雜的事情,在工作的這幾年大致經(jīng)歷過如下幾個(gè)階段:?jiǎn)畏?wù)、多服務(wù)集群、微服務(wù)、持續(xù)集成;在近2年比較穩(wěn)定的選型是微服務(wù)+自動(dòng)化集成的模式:
思考其本質(zhì)的變化邏輯,即為了應(yīng)對(duì)更復(fù)雜的業(yè)務(wù)體系;不管是業(yè)務(wù)拆分還是模型設(shè)計(jì),都是在不斷實(shí)現(xiàn)高內(nèi)聚低耦合 的原則;降低業(yè)務(wù)之間的關(guān)聯(lián)影響,分離業(yè)務(wù)和技術(shù)的高度耦合。
2、業(yè)務(wù)場(chǎng)景
這里先來看一個(gè)經(jīng)典的業(yè)務(wù)場(chǎng)景:電商交易;基于微服務(wù)架構(gòu)的電商交易場(chǎng)景中,通常至少會(huì)涉及如下幾個(gè)核心服務(wù):交易、賬戶、訂單、商品、倉儲(chǔ)、物流;
站在業(yè)務(wù)角度,進(jìn)行模塊化拆分和管理,結(jié)合持續(xù)集成的組件,通??梢暂p松的應(yīng)對(duì)各種復(fù)雜的業(yè)務(wù)場(chǎng)景,但是不存在真正意義上一勞永逸的手段,業(yè)務(wù)變化帶來的各種問題總會(huì)無腦推動(dòng)開發(fā)去尋找更合理的解決方案;
在一次完整的電商交易場(chǎng)景中,實(shí)際上真正涉及到的微服務(wù)遠(yuǎn)不止圖中的幾個(gè),在Trade服務(wù)中交織關(guān)聯(lián)多個(gè)其他服務(wù),在MVC的分層管理下,初期并不會(huì)存在較大風(fēng)險(xiǎn),但是業(yè)務(wù)一旦經(jīng)過多版升級(jí)改造之后,并且還存在版本兼容的要求,會(huì)給人一種極度混亂和不踏實(shí)的感覺;
如果團(tuán)隊(duì)成員的綜合能力較高,并且版本有充足的時(shí)間去設(shè)計(jì)和優(yōu)化,這種問題是可以妥善解決的,如果出現(xiàn)時(shí)間緊任務(wù)重的情況,隨之而來的壓力會(huì)持續(xù)在開發(fā)和測(cè)試之間來回橫跳 ;
解決過相關(guān)業(yè)務(wù)場(chǎng)景的研發(fā)都知道,重構(gòu)加持續(xù)集成能力,結(jié)合嚴(yán)謹(jǐn)?shù)臏y(cè)試,可以應(yīng)對(duì)業(yè)務(wù)的不斷變化;但是在版本兼容的過程中,依然會(huì)導(dǎo)致工程中的代碼膨脹到飛起,特別是出現(xiàn)中場(chǎng)換人的情況,都會(huì)讓接手的人員在被埋和離開中,產(chǎn)生一次劇烈的心態(tài)掙扎。
3、問題分析
在MVC的架構(gòu)模式中,工程通常會(huì)進(jìn)行如下的分層管理:控制層、服務(wù)層、持久層、存儲(chǔ)層;服務(wù)層在特定復(fù)雜的場(chǎng)景中會(huì)做細(xì)化拆分,比如第三方對(duì)接、常用中間件的二次封裝:
對(duì)于在復(fù)雜業(yè)務(wù)線上爭(zhēng)渡的選手來說,對(duì)Mvc分層模式的缺陷是深有體會(huì)的,Service層聚焦大量復(fù)雜的邏輯,通常核心業(yè)務(wù)塊中總會(huì)存在幾個(gè)代碼過千行的實(shí)現(xiàn)邏輯,不管用什么思路和模式去拆分封裝,都很難解決該層不斷擴(kuò)展帶來的膨脹問題。
4、面向過程
在MVC分層中,過程式的代碼極其明顯,通常以數(shù)據(jù)庫表和關(guān)系為基礎(chǔ),映射構(gòu)建相關(guān)實(shí)體對(duì)象,這些實(shí)體對(duì)象并沒有具體的行為和邏輯,只是作為數(shù)據(jù)和結(jié)構(gòu)的載體:
從面向?qū)ο笾蓄惖亩x去看:屬性和行為;而在MVC模式中,絕大多數(shù)實(shí)體都只是作為數(shù)據(jù)的入?yún)⒊鰠⒌慕Y(jié)構(gòu)定義,可以理解為數(shù)據(jù)容器,在MVC的各層之間不斷搬運(yùn)和加工。
基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實(shí)現(xiàn)的后臺(tái)管理系統(tǒng) + 用戶小程序,支持 RBAC 動(dòng)態(tài)權(quán)限、多租戶、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能
三、領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)
相比MVC的分層設(shè)計(jì),領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)(Domain-Driven-Design簡(jiǎn)稱DDD)對(duì)于復(fù)雜業(yè)務(wù)系統(tǒng)的實(shí)現(xiàn),提出了更加合理的解決方案,DDD模式中涉及大量專業(yè)術(shù)語和抽象概念,可以參考EricEvans
的相關(guān)書籍,本文只描述實(shí)踐中的核心概念。
1、分離模式
DDD模型在分層設(shè)計(jì)上,劃分出核心的四層:接入層、應(yīng)用層、領(lǐng)域?qū)?、基礎(chǔ)設(shè)施層;注意這里只是單純站在服務(wù)端的常規(guī)架構(gòu)角度去看,很明顯分離MVC模式中的服務(wù)實(shí)現(xiàn)層的邏輯:
其中領(lǐng)域?qū)邮顷P(guān)鍵所在,用來封裝復(fù)雜的業(yè)務(wù),對(duì)應(yīng)用層提供業(yè)務(wù)管理的核心支撐;整個(gè)模型也更具備縱向思維,有效的緩解單層復(fù)雜度過高的現(xiàn)象;單從模型設(shè)計(jì)上看,在工程中基于該分層去管理代碼包,也可以使每層的設(shè)計(jì)更加清晰和獨(dú)立。
2、設(shè)計(jì)思想
領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)并不是簡(jiǎn)單的分層管理模型,涉及諸多抽象邏輯與專業(yè)術(shù)語,例如:領(lǐng)域、界限上下文、實(shí)體、聚合、值對(duì)象等等;
2.1 領(lǐng)域
領(lǐng)域可以理解為業(yè)務(wù)場(chǎng)景中需要解決的問題合集,是具有范圍和邊界的約束;領(lǐng)域可以拆分多個(gè)子域,通常描述為:核心域、支撐域、通用域:
關(guān)于子域的劃分也是參考業(yè)務(wù)屬性,可以把核心域理解為最關(guān)鍵的業(yè)務(wù)場(chǎng)景,并且需要資源傾斜以應(yīng)對(duì)其不斷的發(fā)展;支撐域可以理解為相對(duì)穩(wěn)定的業(yè)務(wù);通用域偏向系統(tǒng)架構(gòu)層面的公共能力;通過對(duì)領(lǐng)域的拆分實(shí)現(xiàn)業(yè)務(wù)分治,這與微服務(wù)的拆分思想相符合,兩種模式在業(yè)務(wù)角度是比較統(tǒng)一的;
2.2 界限上下文
DDD中最晦澀難懂的一個(gè)抽象概念,特定模型的限界應(yīng)用,不過可以借用原文的比喻會(huì)意一下:細(xì)胞之所以能夠存在,是因?yàn)榧?xì)胞膜限定了什么在細(xì)胞內(nèi),什么在細(xì)胞外, 并且確定了什么物質(zhì)可以通過細(xì)胞膜:
界限上下文的定義涉及粒度的思想,即每個(gè)粒度要具備獨(dú)立性;如上圖倉儲(chǔ)業(yè)務(wù),可以將服務(wù)部署與倉儲(chǔ)子域、倉儲(chǔ)上下文做成一一對(duì)應(yīng)的關(guān)系,或者在倉儲(chǔ)子域中分別定義:倉庫和貨架兩個(gè)上下文;這里具有極大的靈活性,沒有真正意義上的標(biāo)準(zhǔn)可以參考。
2.3 映射關(guān)系
做好界限上下文的劃分,理清各個(gè)上下文之間的關(guān)系,明確業(yè)務(wù)場(chǎng)景中的依賴順序,這樣可以更好的推動(dòng)開發(fā)流程的落地;對(duì)于上下文的關(guān)系描述也遠(yuǎn)不止圖中的這些,還有共享內(nèi)核、合作等等:
- 上下游(U-上游,D下游):描述上下文調(diào)用時(shí)的關(guān)系,服務(wù)調(diào)用方為D,服務(wù)提供方為U;
- 防腐層(Anticorruption-Layer,簡(jiǎn)寫ACL):上下文交互時(shí)封裝的一層,提供對(duì)動(dòng)作的校驗(yàn)、適配、轉(zhuǎn)換等;
- 開放主機(jī)服務(wù),發(fā)布語言(Open-Host-Service簡(jiǎn)寫OHS,Published-Language簡(jiǎn)寫PL):定義訪問協(xié)議;
在上下文交互時(shí),防腐層可以維護(hù)上下文的隔離和獨(dú)立,確保調(diào)用方不直接依賴服務(wù)提供方,從而實(shí)現(xiàn)不同上下文之間的依賴解耦;同時(shí)這也會(huì)帶來大量的對(duì)象轉(zhuǎn)換動(dòng)作;
2.4 建模設(shè)計(jì)
子域和界線上線文完成對(duì)業(yè)務(wù)的拆分切塊,從而進(jìn)行分治;基于防腐層降低各個(gè)界限上下文的耦合程度;聚合思想保證了業(yè)務(wù)問題的解決方案內(nèi)聚;嚴(yán)格的分層模型實(shí)現(xiàn)服務(wù)支撐能力的分散;
- 防腐層(Anticorruption-Layer):上下文交互時(shí)封裝的一層;
- 領(lǐng)域?qū)?Domain-Layer):在分層架構(gòu)中負(fù)責(zé)領(lǐng)域邏輯的設(shè)計(jì)和實(shí)現(xiàn);
- 領(lǐng)域服務(wù)(Domain-Service):行為無法識(shí)別歸屬的實(shí)體時(shí),封裝到領(lǐng)域服務(wù);
- 聚合(Aggregate):相關(guān)對(duì)象的集合,描述核心領(lǐng)域,通常把聚合作為數(shù)據(jù)修改的單元;
- 實(shí)體(Entity):通過標(biāo)識(shí)來定義的對(duì)象,而不是基于屬性,比如Uid標(biāo)識(shí)用戶實(shí)體;
- 值對(duì)象(Value-Object):描述特征或?qū)傩缘珱]有標(biāo)識(shí)的對(duì)象;
- 工廠(Factory):封裝對(duì)象復(fù)雜的創(chuàng)建邏輯與類型;
- 存儲(chǔ)庫(Repository):把存儲(chǔ)、緩存、搜索等資源封裝的機(jī)制,對(duì)應(yīng)領(lǐng)域模型;
領(lǐng)域模型的核心追求目標(biāo):高內(nèi)聚、低耦合;更加抽象的、復(fù)雜的設(shè)計(jì)思想,也同樣意味著落地實(shí)現(xiàn)的難度更高,但不可否認(rèn)領(lǐng)域模型作為復(fù)雜業(yè)務(wù)的解決方案,邏輯上的確更加合理。
3、工程實(shí)踐
領(lǐng)域模型在代碼工程的實(shí)踐中,可以將不同的子域集成到各自的服務(wù)中,也可以在一個(gè)服務(wù)中,通過多個(gè)模塊(Module)進(jìn)行隔離維護(hù),即一個(gè)模塊對(duì)應(yīng)一個(gè)界限上下文;
將業(yè)務(wù)問題進(jìn)行分模塊分層分包的方式進(jìn)行隔離,是代碼工程中的基本手段,這里只是對(duì)組織方式進(jìn)行描述,在實(shí)際的開發(fā)中,要根據(jù)依賴順序進(jìn)行類庫拆包管理;
在程序的執(zhí)行過程中,并不是所有的交互命令都需要經(jīng)過領(lǐng)域?qū)樱瑢?shí)際上大部分業(yè)務(wù)中的查詢命令都是超過增刪改命令的,所以在純讀取數(shù)據(jù)的請(qǐng)求中,應(yīng)用層可以繞開領(lǐng)域?qū)又苯釉L問基礎(chǔ)設(shè)施層,減少一層數(shù)據(jù)處理邏輯。
四、實(shí)踐總結(jié)
最后來討論一些架構(gòu)實(shí)踐的經(jīng)驗(yàn),隨著技術(shù)的不斷發(fā)展和更新?lián)Q代,為解決業(yè)務(wù)問題提供了極大的便利,不管是單服務(wù)中各種成熟的組件,又或者分布式中的微服務(wù)體系,或者聚焦業(yè)務(wù)管理的領(lǐng)域模型;每種架構(gòu)選型都有其適用的場(chǎng)景,不同的選型意味著不一樣的實(shí)現(xiàn)成本;
實(shí)際上在做架構(gòu)選型時(shí),成熟有經(jīng)驗(yàn)的主導(dǎo)者,都極其擅長(zhǎng)做折中處理,也就是常說的退一步海闊天空;通常需要考慮團(tuán)隊(duì)的綜合水平與業(yè)務(wù)需求和產(chǎn)品設(shè)計(jì),當(dāng)然在實(shí)際的協(xié)作流程中多方都是需要相對(duì)讓步的,但是對(duì)質(zhì)量的要求以及核心業(yè)務(wù)的實(shí)現(xiàn)邏輯上是不能打折的。
五、參考源碼
編程文檔:https://gitee.com/cicadasmile/butte-java-note
應(yīng)用倉庫:https://gitee.com/cicadasmile/butte-flyer-parent
審核編輯 :李倩
原文標(biāo)題:微服務(wù)與領(lǐng)域驅(qū)動(dòng)設(shè)計(jì),架構(gòu)實(shí)踐總結(jié)
文章出處:【微信公眾號(hào):芋道源碼】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
-
模塊
+關(guān)注
關(guān)注
7文章
2658瀏覽量
47294 -
架構(gòu)
+關(guān)注
關(guān)注
1文章
506瀏覽量
25430 -
微服務(wù)
+關(guān)注
關(guān)注
0文章
131瀏覽量
7322
原文標(biāo)題:微服務(wù)與領(lǐng)域驅(qū)動(dòng)設(shè)計(jì),架構(gòu)實(shí)踐總結(jié)
文章出處:【微信號(hào):芋道源碼,微信公眾號(hào):芋道源碼】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論