摘要:但新增模塊的結(jié)構(gòu)卻還是大致相同,此即是的經(jīng)典設(shè)計(jì)模式這套模式也被開發(fā)者稱為三駕馬車。領(lǐng)域?qū)佣x負(fù)責(zé)表達(dá)業(yè)務(wù)概念,業(yè)務(wù)狀態(tài)信息以及業(yè)務(wù)規(guī)則。
本文首發(fā)于泊浮目的專欄:https://segmentfault.com/blog...前言
隨著ZStack的版本迭代,其可以掌管的資源也越來越多。但新增模塊的結(jié)構(gòu)卻還是大致相同,此即是ZStack的經(jīng)典設(shè)計(jì)模式——這套模式也被開發(fā)者稱為ZStack三駕馬車。
實(shí)例分析以PrimaryStorage為例,其APIMsg的真正邏輯處理第一站就是PrimaryStorageManagerImpl。
如果是對(duì)特定的PrimaryStorage進(jìn)行操作,將會(huì)通過相應(yīng)的Factory得出對(duì)應(yīng)類型并轉(zhuǎn)發(fā)至相應(yīng)的Base:
private void passThrough(PrimaryStorageMessage pmsg) { PrimaryStorageVO vo = dbf.findByUuid(pmsg.getPrimaryStorageUuid(), PrimaryStorageVO.class); if (vo == null && allowedMessageAfterSoftDeletion.contains(pmsg.getClass())) { PrimaryStorageEO eo = dbf.findByUuid(pmsg.getPrimaryStorageUuid(), PrimaryStorageEO.class); vo = ObjectUtils.newAndCopy(eo, PrimaryStorageVO.class); } Message msg = (Message) pmsg; if (vo == null) { String err = String.format("Cannot find primary storage[uuid:%s], it may have been deleted", pmsg.getPrimaryStorageUuid()); bus.replyErrorByMessageType(msg, errf.instantiateErrorCode(SysErrors.RESOURCE_NOT_FOUND, err)); return; } PrimaryStorageFactory factory = getPrimaryStorageFactory(PrimaryStorageType.valueOf(vo.getType())); PrimaryStorage ps = factory.getPrimaryStorage(vo); ps.handleMessage(msg); }
PrimaryStorageFactory是一個(gè)接口,在此基礎(chǔ)上有各式各樣的實(shí)現(xiàn):如Local、Ceph、NFS等。
public interface PrimaryStorageFactory { PrimaryStorageType getPrimaryStorageType(); PrimaryStorageInventory createPrimaryStorage(PrimaryStorageVO vo, APIAddPrimaryStorageMsg msg); PrimaryStorage getPrimaryStorage(PrimaryStorageVO vo); PrimaryStorageInventory getInventory(String uuid); }
這就像現(xiàn)實(shí)中的模型一樣——在ZStack中可以有PrimaryStorage,而且可以有不同類型的PrimaryStorage:
PrimaryStorage:
Local
Ceph
NFS
這在軟件工程中即是一種分離領(lǐng)域(Layered Architecture)的具象。應(yīng)用層對(duì)應(yīng)ZStack的ManagerImpl,而Base更像是領(lǐng)域?qū)印?/p> 應(yīng)用層
應(yīng)用層的定義應(yīng)該是:
定義軟件要完成的任務(wù),并且指揮表達(dá)領(lǐng)域概念的對(duì)象來解決問題。這一層負(fù)責(zé)的工作對(duì)業(yè)務(wù)來說意義重大,也是與其他系統(tǒng)的應(yīng)用層進(jìn)行交互的必要渠道。
應(yīng)用層要盡量簡(jiǎn)單,不包含業(yè)務(wù)規(guī)則或者知識(shí),而只為下一次的領(lǐng)域?qū)ο髤f(xié)調(diào)任務(wù),分配工作,使它們互相協(xié)作。它沒有反映業(yè)務(wù)情況的狀態(tài),但是卻可以具有另外一種狀態(tài),為用戶或程序顯示某個(gè)任務(wù)的進(jìn)度。
而在ZStack中,的確也像上面說的如此。在源碼中我們可以看到,對(duì)實(shí)例操作的API全部被轉(zhuǎn)發(fā)到了Base層去,而Manager這里handle的往往是一些過濾性、Get型API,如APIListPrimaryStorageMsg、APIGetPrimaryStorageMsg、APIGetPrimaryStorageTypesMsg等。
Manager即是API(這里API不僅僅是APIxxxMsg,同時(shí)包含用于通信的內(nèi)部Msg。注意,它們都implements自Message這個(gè)接口)的入口,以及用于管理服務(wù)的生命周期。
領(lǐng)域?qū)?/b>定義:
負(fù)責(zé)表達(dá)業(yè)務(wù)概念,業(yè)務(wù)狀態(tài)信息以及業(yè)務(wù)規(guī)則。盡管保存業(yè)務(wù)狀態(tài)的技術(shù)細(xì)節(jié)由基礎(chǔ)設(shè)施層(在ZStack如DataBaseFacade即是),但是反映業(yè)務(wù)情況的狀態(tài)是由本層控制并且使用的。注意,領(lǐng)域?qū)邮菢I(yè)務(wù)軟件的核心。
以PrimaryStorageBase為例,其本身對(duì)應(yīng)了DB中的一條記錄,并且在改變狀態(tài)后也Refresh自己。并對(duì)操作多帶帶實(shí)例的Msg進(jìn)行handle。
通信雖然分了層,并且關(guān)系是松散的。但是各個(gè)層之間也是需要通信的,那么層與層之間只能是單向的。上層可以直接使用或操作下層元素,方法是通過調(diào)用下層元素的公共接口,保持對(duì)下層元素的引用(至少是暫時(shí)的),以及采用常規(guī)的交互手段。而如果下層元素需要與上層元素通信,則需要采用另一種通信機(jī)制——比如回調(diào)或者Observers模式(在ZStack中即是ExtensionPoint)。
回調(diào)我們還是以PrimaryStorageBase為例。在其做鏈接操作時(shí),邏輯如下:
private void doConnect(ConnectParam param, final Completion completion) { thdf.chainSubmit(new ChainTask(completion) { @Override public String getSyncSignature() { return String.format("reconnect-primary-storage-%s", self.getUuid()); } @Override public void run(SyncTaskChain chain) { changeStatus(PrimaryStorageStatus.Connecting); connectHook(param, new Completion(chain, completion) { @Override public void success() { self = dbf.reload(self); changeStatus(PrimaryStorageStatus.Connected); logger.debug(String.format("successfully connected primary storage[uuid:%s]", self.getUuid())); RecalculatePrimaryStorageCapacityMsg rmsg = new RecalculatePrimaryStorageCapacityMsg(); rmsg.setPrimaryStorageUuid(self.getUuid()); bus.makeLocalServiceId(rmsg, PrimaryStorageConstant.SERVICE_ID); bus.send(rmsg); tracker.track(self.getUuid()); completion.success(); chain.next(); } @Override public void fail(ErrorCode errorCode) { tracker.track(self.getUuid()); self = dbf.reload(self); changeStatus(PrimaryStorageStatus.Disconnected); logger.debug(String.format("failed to connect primary storage[uuid:%s], %s", self.getUuid(), errorCode)); completion.fail(errorCode); chain.next(); } }); } @Override public String getName() { return getSyncSignature(); } }); }
而不同的connectHook都有不同的實(shí)現(xiàn)。
在抽象等級(jí)上,PrimaryStorageBase是比圖中的這些Base高的。而這類具象Base可以Message返回Success或者Fail使高層Base做出不同的決策。
繼續(xù),在PrimaryStorageBase中,其中handle APIAttachPrimaryStorageToClusterMsg的地方會(huì)做事件發(fā)送:
extpEmitter.preAttach(self, msg.getClusterUuid());
其會(huì)發(fā)送向:
在這里,一個(gè)Base通過了Observers模式向某個(gè)ManagerImpl發(fā)送了事件,實(shí)現(xiàn)了下層往上層的通信。
小結(jié)在大型軟件工程中,我們通常會(huì)給這樣的應(yīng)用劃分層次。分別在每層中進(jìn)行設(shè)計(jì),使其具有內(nèi)聚性并且只依賴于它的下層,而下層與上層也只有松散的耦合。這使得模型含義豐富,結(jié)構(gòu)清晰。也使得整個(gè)應(yīng)用架構(gòu)更加茁壯。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/68279.html
摘要:但在實(shí)際的二次開發(fā)中,這些做法未必能夠完全滿足需求。在源碼剖析之核心庫(kù)鑒賞一文中,我們了解到是的基礎(chǔ)設(shè)施之一,同時(shí)也允許通過顯示聲明的方式來聲明。同理,一些也可以使用繼承進(jìn)行擴(kuò)展。 本文首發(fā)于泊浮目的專欄:https://segmentfault.com/blog... 前言 在ZStack博文-5.通用插件系統(tǒng)中,官方提出了幾個(gè)較為經(jīng)典的擴(kuò)展方式。但在實(shí)際的二次開發(fā)中,這些做法未必...
摘要:源碼剖析之設(shè)計(jì)模式鑒賞策略模式小結(jié)在這篇文章中筆者和大家分享幾個(gè)減少的小由于這些都會(huì)有一定的限制因此還向大家介紹了幾個(gè)能夠避免寫出糟糕的的設(shè)計(jì)模式并使用觀察者模式簡(jiǎn)單的改進(jìn)了仲裁者模式的例子 本文首發(fā)于數(shù)據(jù)浮云:https://mp.weixin.qq.com/s?__... 在寫代碼的日常中,if...else語(yǔ)句是極為常見的.正因其常見性,很多同學(xué)在寫代碼的時(shí)候并不會(huì)去思考其在目...
摘要:能夠整體地替換算法,能讓我們輕松地以不同的算法去解決一個(gè)問題,這種模式就是模式。這個(gè)類是在發(fā)布前常在中被使用的一個(gè)類,代碼如下以為例,從語(yǔ)義上來說就是為了中的每個(gè)元素調(diào)用函數(shù)。 本文首發(fā)于泊浮目的專欄:https://segmentfault.com/blog... 前言 無論什么程序,其目的都是解決問題。而為了解決問題,我們又需要編寫特定的算法。使用Strategy模式可以整體地替...
摘要:本文首發(fā)于泊浮目的專欄在語(yǔ)言中,有一個(gè)關(guān)鍵字叫做其作用是在函數(shù)前執(zhí)行。一般有兩種用法在該函數(shù)拋出異常時(shí)執(zhí)行。在該函數(shù)返回前執(zhí)行。這里的放入來自系統(tǒng)啟動(dòng)時(shí)利用反射所做的一個(gè)行為。因此并不會(huì)影響使用時(shí)的性能。 本文首發(fā)于泊浮目的專欄:https://segmentfault.com/blog... 在Go語(yǔ)言中,有一個(gè)關(guān)鍵字叫做defer——其作用是在函數(shù)return前執(zhí)行。在ZStac...
摘要:本文首發(fā)于泊浮目的專欄在語(yǔ)言中,有一個(gè)關(guān)鍵字叫做其作用是在函數(shù)前執(zhí)行。一般有兩種用法在該函數(shù)拋出異常時(shí)執(zhí)行。在該函數(shù)返回前執(zhí)行。這里的放入來自系統(tǒng)啟動(dòng)時(shí)利用反射所做的一個(gè)行為。因此并不會(huì)影響使用時(shí)的性能。 本文首發(fā)于泊浮目的專欄:https://segmentfault.com/blog... 在Go語(yǔ)言中,有一個(gè)關(guān)鍵字叫做defer——其作用是在函數(shù)return前執(zhí)行。在ZStac...
閱讀 2332·2021-10-08 10:04
閱讀 1105·2021-09-03 10:40
閱讀 1158·2019-08-30 15:53
閱讀 3315·2019-08-30 13:13
閱讀 2932·2019-08-30 12:55
閱讀 2286·2019-08-29 13:21
閱讀 1355·2019-08-26 12:12
閱讀 2761·2019-08-26 10:37