拆分:分解单块系统——《微服务设计》读书笔记
通常,我們可能已有有一個(gè)巨大的單塊系統(tǒng),如何實(shí)現(xiàn)微服務(wù),我們需要把它分解。
從哪里開始拆分:接縫
? ? ??接縫:從接縫處可以抽取相對(duì)獨(dú)立的一部分代碼,對(duì)這部分代碼的修改不會(huì)影響系統(tǒng)的其他部分。這些接縫就可以作為服務(wù)的邊界。
? ? ? 那如何識(shí)別出接縫呢?我們可以使用前面所提到的限界上下文,也可通過程序中的命名空間來幫助我們,也可以通過工具來幫助我們,如structure101這樣的工具來可視化包之間的依賴。
雜亂依賴的根源:數(shù)據(jù)庫(kù)
? ? ? 為什么這么說?因?yàn)?#xff0c;通常情況下,我們?cè)跇I(yè)務(wù)層的代碼已經(jīng)通過分層組織到相應(yīng)的包中了,但是只有數(shù)據(jù)庫(kù)是共用的,數(shù)據(jù)庫(kù)對(duì)所有的代碼都允許訪問,是一個(gè)巨大的API。我們舉例說明:有一張倉(cāng)儲(chǔ)表,它被“產(chǎn)品目錄”、“倉(cāng)庫(kù)”、“財(cái)務(wù)”等服務(wù)所共用,那么在單塊應(yīng)用程序中,通常會(huì)是下面的結(jié)構(gòu):
? ? ?
? ? ? 對(duì)于同一張表被多個(gè)限界上下文使用的場(chǎng)景,我們應(yīng)該如何處理?以下是一些處理的步驟和原則 :
? ? ? 一.分清代碼中對(duì)數(shù)據(jù)庫(kù)進(jìn)行讀寫的部分
? ? ? 我們需要厘清代碼是如何訪問數(shù)據(jù)庫(kù)的,在什么地方讀,在什么地方寫?他們分別位于什么樣的上下文中。
? ? ? 二.打破外鍵關(guān)系
? ? ? 對(duì)于表與表之間的外鍵關(guān)系,如果這兩張表需要被拆分至兩個(gè)微服務(wù)中,我們可能需要放棄外鍵關(guān)系,同時(shí)把這個(gè)約束關(guān)系放到代碼中實(shí)現(xiàn),我們可能還需要實(shí)現(xiàn)跨服務(wù)的一致性檢查,或者周期性觸發(fā)清理數(shù)據(jù)的任務(wù)。
? ? ? 我們可以通過類似于SchemeSpy這樣的工具來分析數(shù)據(jù)庫(kù)表之間的依賴關(guān)系。
? ? ? 三.共享靜態(tài)數(shù)據(jù)
? ? ? 比如,國(guó)家、部門之類的數(shù)據(jù)都是各個(gè)微服務(wù)之間經(jīng)常使用的,這些數(shù)據(jù)的特征是不會(huì)經(jīng)常變,而且是通用性高。這些數(shù)據(jù)在微服務(wù)劃分之后該如何處理呢?
? ? ? 方法一:我們可以為每個(gè)微服務(wù)復(fù)制一份這樣的數(shù)據(jù),但是這個(gè)會(huì)導(dǎo)致數(shù)據(jù)的一致性問題;
? ? ? 方法二:把共享的數(shù)據(jù)放入代碼之中,比如放在屬性文件 中,或者簡(jiǎn)單地放在一個(gè)枚舉中,但數(shù)據(jù)一致性仍然存在。
? ? ? 方法三:把這些靜態(tài)數(shù)據(jù)放在一個(gè)單獨(dú)的服務(wù)中。
? ? ? 四.共享數(shù)據(jù)
? ? ? 如果不同的微服務(wù)都使用了同一張表,比如倉(cāng)庫(kù)和財(cái)務(wù)都用到了客戶信息表,這種情況下該如何分享?其實(shí)這種情況很常見:領(lǐng)域概念不是在代碼中建模,相反是在數(shù)據(jù)庫(kù)中隱式地進(jìn)行建模。這里缺失的領(lǐng)域概念是客戶,因而我們需要提供一個(gè)新的服務(wù):客戶服務(wù)。
? ? ? 五.共享表
? ? ? 與共享數(shù)據(jù)不同的是:不同的微服務(wù)也會(huì)使用同一張表,但兩者修改的部分不一樣,這樣的情況下,我們可以把這張表拆分出兩張表,分別供兩個(gè)微服務(wù)使用。
? ? ? 六.實(shí)施拆分
? ? ? 通常,我們推薦先分離數(shù)據(jù)庫(kù)結(jié)構(gòu)然后對(duì)代碼進(jìn)行拆分。表結(jié)構(gòu)分離之后,對(duì)于原先的某個(gè)動(dòng)作而言,對(duì)數(shù)據(jù)庫(kù)的訪問次數(shù)可能會(huì)變多。這也是我們需要考慮的問題,這里涉及到分布式事務(wù)的相關(guān)問題。
另外,先拆分?jǐn)?shù)據(jù)庫(kù)但不分離代碼的好處在于,可以隨時(shí)選擇回退這些修改或是繼續(xù),而不影響服務(wù)的任何消費(fèi)者。
分布式事務(wù)
? ? ? 一個(gè)事務(wù)可以幫助系統(tǒng)從一個(gè)一致性的狀態(tài)遷移到另一個(gè)一致的狀態(tài),要么全部都做,要么什么都不做。
? ? ? ?在單塊結(jié)構(gòu)中,所有的創(chuàng)建或者更新都可以在一個(gè)事務(wù)邊界內(nèi)完成,分離數(shù)據(jù)庫(kù)之后,這種好處就沒有了。在分布式事務(wù)中,我們有可能面臨一個(gè)操作成功,而另一個(gè)操作失敗的局而,我們?cè)撊绾翁幚磉@些問題?
? ? ? ?方法1:補(bǔ)償機(jī)制——最終一致性
? ? ? ?對(duì)于失敗的動(dòng)作,我們進(jìn)行重復(fù)觸發(fā),只要在系統(tǒng)可接受的時(shí)間范圍內(nèi),最終一致性是可以接受的。
???????方法2:回滾機(jī)制
? ? ? ?對(duì)于失敗的動(dòng)作,我們可以選擇回滾。但是回滾也失敗的呢?這個(gè)時(shí)間,要么我們?cè)谀硞€(gè)時(shí)間重試回滾操作,或者提供一些自動(dòng)化的操作或界面操作來清除這些不一致的狀態(tài)。
? ? ? 方法3:分布式事務(wù)
? ? ? 我們可以使用事務(wù)管理器來統(tǒng)一編排橫跨多個(gè)服務(wù)的事務(wù),分布式的事務(wù)會(huì)保證整個(gè)系統(tǒng)處于一致的狀態(tài),唯一不同的是,這里的事務(wù)會(huì)運(yùn)行在不同系統(tǒng)的不同進(jìn)程中,通常它們之間使用網(wǎng)絡(luò)進(jìn)行通信。
? ? ? 分布式事務(wù)的常見算法是兩段提交,在這種方式中,首先是投票階段,在這個(gè)階段,每個(gè)參與者都會(huì)告訴事務(wù)管理器是否應(yīng)該繼續(xù),如果事務(wù)管理器收到所有的投票都是成功,則事務(wù)管理器會(huì)告知各個(gè)參與者執(zhí)行提交操作,只要收到一個(gè)否定的投標(biāo),事務(wù)管理器就會(huì)讓所有的參與者回退。
? ? ? 但兩段提交也有缺點(diǎn),首先所有的參與者都等待中央?yún)f(xié)調(diào)進(jìn)程的指令,從而很容易導(dǎo)致系統(tǒng)的中斷,如果事務(wù)管理器宕機(jī)了,處于等待狀態(tài)的事務(wù)就永遠(yuǎn)無法完成;如果有一個(gè)參與者在投票階段發(fā)送消息失敗,則所有的其他參與者都會(huì)被阻,投票之后的提交也可能會(huì)失敗;另外中央?yún)f(xié)調(diào)進(jìn)程也可能使用鎖,這樣會(huì)對(duì)系統(tǒng)的擴(kuò)展帶來影響。因而這種算法并不是萬(wàn)無一失的。
? ? ? 如果確實(shí)存在保持一致懷的場(chǎng)合,應(yīng)該盡量避免把它們放在不同的地方。
?
又一個(gè)難點(diǎn):報(bào)表數(shù)據(jù)庫(kù)
? ? ? 報(bào)表通常需要來自組織內(nèi)各個(gè)部分的數(shù)據(jù),在以往的單塊結(jié)構(gòu)來說,這是很方便的。但也存在一些缺點(diǎn):首先是修改表結(jié)構(gòu)的風(fēng)險(xiǎn)增大;再者則是報(bào)表系統(tǒng)的優(yōu)先手段有限,比如關(guān)系型數(shù)據(jù)庫(kù)對(duì)于海量的數(shù)據(jù)不能呈現(xiàn)很好的支持,而MongoDB則地文檔存儲(chǔ)有其獨(dú)特的優(yōu)越性。
? ? ? 一.通過服務(wù)調(diào)用來獲取數(shù)據(jù)
? ? ? 報(bào)表數(shù)據(jù)通常需要大量的數(shù)據(jù),通過服務(wù)提供接口來一條條調(diào)用很顯示是不太合適的,這樣非常低效而且對(duì)服務(wù)來說負(fù)載過重。
? ? ? 我們可以一次性返回分頁(yè)的多條記錄,或者在本地將數(shù)據(jù)導(dǎo)出到文件文件的地址返回給調(diào)用方以供使用。
? ? ? 二.數(shù)據(jù)導(dǎo)出
? ? ? 我們也可以把報(bào)表數(shù)據(jù)周期性的導(dǎo)出,推送到報(bào)表數(shù)據(jù)庫(kù),但這樣不同微服務(wù)的數(shù)據(jù)又集成到一起的,這時(shí)我們可以使用一些技術(shù)來屏蔽這些耦合,比如視圖
? ? ? 三.事件數(shù)據(jù)導(dǎo)出
? ? ? 在每次數(shù)據(jù)發(fā)生變化時(shí),數(shù)據(jù)提供方也會(huì)提供一些事件,數(shù)據(jù)訂閱方可以將這些數(shù)據(jù)導(dǎo)出到報(bào)表數(shù)據(jù)庫(kù)中,這樣源數(shù)據(jù)與數(shù)據(jù)之間的耦合就消除掉了,我們只需要綁定到服務(wù)所發(fā)送的事件即可。
? ? ? 不同前面的周期性導(dǎo)出數(shù)據(jù),這里的事件數(shù)據(jù)是實(shí)時(shí),所以能讓數(shù)據(jù)更快地流入報(bào)表系統(tǒng)。
? ? ? 另外,我們只需要對(duì)新事件產(chǎn)生的新數(shù)據(jù)進(jìn)行處理,即處理增量數(shù)據(jù),這樣的操作會(huì)更加高效。
? ? ? 而缺點(diǎn)在于事件數(shù)據(jù)必須以事件的形式廣播出去,同時(shí)在數(shù)據(jù)量時(shí),不容易進(jìn)行擴(kuò)展,而前面的數(shù)據(jù)導(dǎo)出的方式,可以在數(shù)據(jù)庫(kù)級(jí)別進(jìn)行擴(kuò)展。
? ? ? 四.數(shù)據(jù)導(dǎo)出的備份
? ? ? 這里是整庫(kù)備份,因而也會(huì)造成不同微服務(wù)之間數(shù)據(jù)的耦合。
?
參考
? ? ? 《微服務(wù)設(shè)計(jì)》(Sam Newman 著 / 崔力強(qiáng) 張駿 譯)
相關(guān)文章:?
微服務(wù)的概念——《微服務(wù)設(shè)計(jì)》讀書筆記
微服務(wù)架構(gòu)師的職責(zé)——《微服務(wù)設(shè)計(jì)讀書筆記》
建模:確定服務(wù)的邊界——《微服務(wù)設(shè)計(jì)》讀書筆記
微服務(wù)集成——《微服務(wù)設(shè)計(jì)》讀書筆記
服務(wù)的協(xié)作:服務(wù)間的消息傳遞——《微服務(wù)設(shè)計(jì)》讀書筆記
原文地址:http://www.cnblogs.com/gudi/p/6667107.html
.NET社區(qū)新聞,深度好文,微信中搜索dotNET跨平臺(tái)或掃描二維碼關(guān)注
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)總結(jié)
以上是生活随笔為你收集整理的拆分:分解单块系统——《微服务设计》读书笔记的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 用.netcore写一个简单redis驱
- 下一篇: 理解C# 4 dynamic(4) –