您好,登錄后才能下訂單哦!
這篇文章將為大家詳細(xì)講解有關(guān)Java從單體架構(gòu)升級(jí)到微服務(wù)要注意哪些問題,小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。
Java是一門面向?qū)ο缶幊陶Z言,可以編寫桌面應(yīng)用程序、Web應(yīng)用程序、分布式系統(tǒng)和嵌入式系統(tǒng)應(yīng)用程序。
由于近年來的移動(dòng)端的發(fā)展和 2C模式 的紅利,一些在風(fēng)口的企業(yè)的業(yè)務(wù)得到爆發(fā)式增長。從架構(gòu)層面來說,業(yè)務(wù)驅(qū)動(dòng)技術(shù)的變革,所以微服務(wù)架構(gòu)的概念得到很多企業(yè)的青睞,因?yàn)榭梢越鉀Q服務(wù)的大流量和高并發(fā)以及穩(wěn)定性的要求。
但是任何架構(gòu)設(shè)計(jì)不是一蹴而就的,不能從起步就開始使用微服務(wù),一般都是先通過單體架構(gòu)來快速實(shí)現(xiàn)需求和搶占市場,然后再迭代式擴(kuò)展。不能一口氣吃個(gè)胖子。
這幾年自己有經(jīng)歷從單體到微服務(wù)的架構(gòu)演變,也有直接參與到已經(jīng)落地的微服務(wù)架構(gòu)的項(xiàng)目中。見過好的架構(gòu)設(shè)計(jì),也見過一些孬的設(shè)計(jì)。好的架構(gòu)設(shè)計(jì),代碼結(jié)構(gòu)優(yōu)雅,分層清晰,業(yè)務(wù)邊界劃分明朗,業(yè)務(wù)開發(fā)人員職責(zé)清晰。不好的設(shè)計(jì)就會(huì)導(dǎo)致代碼混亂難以維護(hù),對新需求無法快速應(yīng)變,開發(fā)人員容易在補(bǔ)丁上打補(bǔ)丁,最后造成積重難返不得不重構(gòu)。
架構(gòu)師需要從業(yè)務(wù)層面和未來業(yè)務(wù)發(fā)展有個(gè)全面的規(guī)劃,讓架構(gòu)高可用,易擴(kuò)展,靈活易使用,隱藏其復(fù)雜性。好的架構(gòu)會(huì)讓下面的業(yè)務(wù)開發(fā)人員按照既定的模式“傻瓜式”編程。
既然第一步是單體架構(gòu),那么好的單體架構(gòu)設(shè)計(jì),為我們后期的微服務(wù)拆分會(huì)有事半功倍的效果。避免重復(fù)勞動(dòng)和過多的重寫。我們可以從這些方面進(jìn)行一些有效的設(shè)計(jì)。
如果對未來的架構(gòu)有微服務(wù)的考慮,那么在單體架構(gòu)的時(shí)候就需要理清業(yè)務(wù)邊界的問題,常見的簡單劃分就是以業(yè)務(wù)區(qū)分,例如:用戶,商品,訂單,支付,權(quán)限等等,具體的拆分程度可根據(jù)自身業(yè)務(wù)量和需要做劃分。
當(dāng)前流行的 DDD(領(lǐng)域驅(qū)動(dòng)設(shè)計(jì))可以作為一個(gè)指導(dǎo)原則,但是 DDD 比較偏向于理論,需要執(zhí)行人員有良好的專業(yè)能力才能實(shí)施的比較好。
業(yè)務(wù)區(qū)分好之后,就是項(xiàng)目代碼模塊的設(shè)計(jì)。在代碼層我們需要根據(jù)MVC的模式,建議的代碼設(shè)計(jì)層次如下:
├─demo-common │ │ demo-common.iml │ │ pom.xml │ │ │ └─src │ ├─main │ │ ├─java │ │ └─resources │ └─test │ └─java ├─demo-dao │ │ demo-dao.iml │ │ pom.xml │ │ │ └─src │ ├─main │ │ ├─java │ │ └─resources │ └─test │ └─java ├─demo-service │ │ demo-service.iml │ │ pom.xml │ │ │ └─src │ ├─main │ │ ├─java │ │ └─resources │ └─test │ └─java └─demo-web │ demo-web.iml │ pom.xml │ └─src ├─main │ ├─java │ └─resources └─test └─java
主要包含4個(gè) module 模塊
demo-common:基礎(chǔ)模塊,枚舉,常亮類,工具類,配置類。
demo-dao:Dao層,mapper接口,mapper.xml。
demo-service:服務(wù)接口提供層,業(yè)務(wù)service接口。
demo-web:web層,Controller類,服務(wù)接口,與外部進(jìn)行交互。
各模塊之間的依賴關(guān)系為:
項(xiàng)目 Module 模塊設(shè)計(jì)完成之后,每個(gè)模塊的內(nèi)部 package 包如何設(shè)計(jì)呢?通常有兩種劃分模式:根據(jù)業(yè)務(wù)模塊然后內(nèi)部按MVC劃分,根據(jù)MVC模式然后內(nèi)部按業(yè)務(wù)劃分。
1、根據(jù)業(yè)務(wù)模塊劃分,就是將每個(gè)業(yè)務(wù)模塊作為一個(gè) package,然后每個(gè)package里面有自己的 MVC,這樣就做到業(yè)務(wù)模塊的隔離。
2、根據(jù) MVC 模式劃分,先根據(jù) MVC模式劃分不同的包,service,serviceImpl,dto等,然后再是各個(gè)業(yè)務(wù)自己的模型和服務(wù)接口。
針對上述的兩個(gè)劃分模式,個(gè)人的選擇是根據(jù)業(yè)務(wù)模式劃分,這樣的包設(shè)計(jì)與后期微服務(wù)拆分有良好的匹配度,拆分的時(shí)候只需要將每個(gè)業(yè)務(wù)包下的代碼 Copy 到新的微服務(wù)中就行了,易遷移變動(dòng)小。每個(gè)模塊中對不同的業(yè)務(wù)通過 package 包名進(jìn)行劃分,例如:com.example.jajian.service.order、com.example.jajian.service.user等。
└─src ├─main │ ├─java │ │ └─com │ │ └─example │ │ └─jajian │ │ ├─common │ │ │ BaserService.java │ │ │ │ │ └─service │ │ ├─order │ │ │ ├─dto │ │ │ │ OrderDto.java │ │ │ │ │ │ │ └─service │ │ │ │ OrderService.java │ │ │ │ │ │ │ └─impl │ │ │ OrderServiceImpl.java │ │ │ │ │ ├─pay │ │ │ ├─dto │ │ │ │ PayDto.java │ │ │ │ │ │ │ └─service │ │ │ │ PayService.java │ │ │ │ │ │ │ └─impl │ │ │ PayServiceImpl.java │ │ │ │ │ └─user │ │ ├─dto │ │ │ UserDto.java │ │ │ │ │ └─service │ │ │ UserService.java │ │ │ │ │ └─impl │ │ UserServiceImpl.java │ │ │ └─resources └─test └─java
這樣劃分有什么好處?我們單體架構(gòu)的時(shí)候這樣開發(fā),當(dāng)需要拆分成微服務(wù)的時(shí)候就可以直接將業(yè)務(wù)包拆分出去,因?yàn)槊總€(gè)業(yè)務(wù)包里面就已經(jīng)包含了所有的當(dāng)前業(yè)務(wù)的關(guān)聯(lián)業(yè)務(wù)類。
單表關(guān)聯(lián)由于業(yè)務(wù)需要而且簡單方便易使用,所以多表關(guān)聯(lián)查詢在單體服務(wù)中是普遍存在的,如果我們后期不需要做服務(wù)拆分則可以不需要考慮這方面的限制。
但是如果后期有微服務(wù)的規(guī)劃,那么單體服務(wù)的時(shí)候如果沒有做這個(gè)方面的限制,mybatis 的 mapper.xml中有過多的多表關(guān)聯(lián)查詢,這些關(guān)聯(lián)查詢會(huì)嚴(yán)重影響服務(wù)拆分的進(jìn)度和復(fù)雜度。
如果同屬于一個(gè)業(yè)務(wù)領(lǐng)域則可以使用關(guān)聯(lián)查詢,而那些微服務(wù)拆分后屬于不同領(lǐng)域的業(yè)務(wù)則應(yīng)避免使用多表關(guān)聯(lián)查詢,因?yàn)椴煌臉I(yè)務(wù)領(lǐng)域后期會(huì)被隔離拆分到不同的服務(wù)當(dāng)中,即數(shù)據(jù)庫表都是分布在不同的服務(wù)器上,所有服務(wù)之間都是通過RPC方式進(jìn)行通信,關(guān)聯(lián)查詢這時(shí)是無法處理的。
常看到很多 coder 會(huì)在Controller 層做一些業(yè)務(wù)處理,個(gè)人認(rèn)為這是很不規(guī)范的。Controller層是控制層,是和前端進(jìn)行數(shù)據(jù)轉(zhuǎn)換的,這里我們應(yīng)該只做請求的接受和返回,也無需做一些異常的try...catch...的捕獲,異常可以通過全局通用攔截器統(tǒng)一進(jìn)行攔截然后返回給前端異常提示語,提升代碼的簡潔性。
所有的參數(shù)校驗(yàn)也放到 service層,因?yàn)槿绻?wù)內(nèi)部調(diào)用也可以使用提高代碼的共用度。當(dāng)然分層領(lǐng)域模型最好也能區(qū)分開,
DO(Data Object):此對象與數(shù)據(jù)庫表結(jié)構(gòu)--對應(yīng),通過DAO層向上傳輸數(shù)據(jù)源對象。
DTO(Date Transfer Object):數(shù)據(jù)傳輸對象,service或Manager向外傳輸?shù)膶ο蟆?/p>
VO(View Object):顯示層的對象,通常是Web向模板渲染引擎層傳輸?shù)膶ο蟆?/p>
這樣區(qū)分開的好處是,當(dāng)你需要對展示層數(shù)據(jù)進(jìn)行特殊定制化的時(shí)候可以靈活變通,例如針對用戶隱私信息身份證號(hào),手機(jī)號(hào)碼脫敏處理,或者用戶ID加密顯示等。
最后就是統(tǒng)一通用返回類了,通過這種格式的封裝我們將數(shù)據(jù)格式進(jìn)行全局格式化,這里的狀態(tài)碼可以自己設(shè)計(jì)的更詳細(xì)一點(diǎn)。
public class CommonResult<T> { public static final String CODE_SUCCESS = "0"; public static final String CODE_FAILED = "9999"; private String code; private T data; private String msg; private CommonResult(String code, T data, String msg) { this.code = code; this.data = data; this.msg = msg; } public boolean isSuccess() { return CODE_SUCCESS.equals(code); } public static <T> CommonResult<T> success() { return new CommonResult<>(CODE_SUCCESS, null, null); } public static <T> CommonResult<T> success(T data) { return new CommonResult<>(CODE_SUCCESS, data, null); } public static <T> CommonResult<T> success(T data, String msg) { return new CommonResult<>(CODE_SUCCESS, data, msg); } public static <T> CommonResult<T> failed() { return new CommonResult<>(CODE_FAILED, null, null); } public static <T> CommonResult<T> failed(String errorCode, String msg) { return new CommonResult<>(errorCode, null, msg); } public static <T> CommonResult<T> failed(String msg) { return new CommonResult<>(CODE_FAILED, null, msg); } public static <T> CommonResult<T> failed(T data, String msg) { return new CommonResult<>(CODE_FAILED, data, msg); } public static <T> CommonResult<T> failed(String errorCode, T data, String msg) { return new CommonResult<>(errorCode, data, msg); } // 省略 setter、getter }
關(guān)于“Java從單體架構(gòu)升級(jí)到微服務(wù)要注意哪些問題”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺得文章不錯(cuò),請把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。