日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

如何一步一步用DDD设计一个电商网站(十三)—— 领域事件扩展

發(fā)布時(shí)間:2024/8/26 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 如何一步一步用DDD设计一个电商网站(十三)—— 领域事件扩展 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

本系列所有文章

如何一步一步用DDD設(shè)計(jì)一個(gè)電商網(wǎng)站(一)—— 先理解核心概念

如何一步一步用DDD設(shè)計(jì)一個(gè)電商網(wǎng)站(二)—— 項(xiàng)目架構(gòu)

如何一步一步用DDD設(shè)計(jì)一個(gè)電商網(wǎng)站(三)—— 初涉核心域

如何一步一步用DDD設(shè)計(jì)一個(gè)電商網(wǎng)站(四)—— 把商品賣給用戶

如何一步一步用DDD設(shè)計(jì)一個(gè)電商網(wǎng)站(五)—— 停下腳步,重新出發(fā)

如何一步一步用DDD設(shè)計(jì)一個(gè)電商網(wǎng)站(六)—— 給購(gòu)物車加點(diǎn)料,集成售價(jià)上下文

如何一步一步用DDD設(shè)計(jì)一個(gè)電商網(wǎng)站(七)—— 實(shí)現(xiàn)售價(jià)上下文

如何一步一步用DDD設(shè)計(jì)一個(gè)電商網(wǎng)站(八)—— 會(huì)員價(jià)的集成

如何一步一步用DDD設(shè)計(jì)一個(gè)電商網(wǎng)站(九)—— 小心陷入值對(duì)象持久化的坑

如何一步一步用DDD設(shè)計(jì)一個(gè)電商網(wǎng)站(十)—— 一個(gè)完整的購(gòu)物車

如何一步一步用DDD設(shè)計(jì)一個(gè)電商網(wǎng)站(十一)—— 最后的準(zhǔn)備

如何一步一步用DDD設(shè)計(jì)一個(gè)電商網(wǎng)站(十二)—— 提交并生成訂單

如何一步一步用DDD設(shè)計(jì)一個(gè)電商網(wǎng)站(十三)—— 領(lǐng)域事件擴(kuò)展

?

?

閱讀目錄

  • 前言
  • 回顧
  • 本地的一致性
  • 領(lǐng)域事件發(fā)布出現(xiàn)異常
  • 訂閱者處理出現(xiàn)異常
  • 結(jié)語

?

一、前言

  上篇中我們初步運(yùn)用了領(lǐng)域事件,其中還有一些問題我們沒有解決,所以實(shí)現(xiàn)是不健壯的,下面先來回顧一下。

?

二、回顧

  先貼一下上篇中的遺留的問題:

public Result Create(OrderRequest orderRequest){if (!string.IsNullOrWhiteSpace(orderRequest.CouponId)){var couponResult = DomainRegistry.SellingPriceService().IsCouponCanUse(orderRequest.CouponId, orderRequest.OrderTime);if (!couponResult.IsSuccess)return Result.Fail(couponResult.Msg);}var orderId = DomainRegistry.OrderRepository().NextIdentity();var order = Domain.Order.Aggregate.Order.Create(orderId, orderRequest.UserId, orderRequest.Receiver,orderRequest.CountryId, orderRequest.CountryName, orderRequest.ProvinceId, orderRequest.ProvinceName,orderRequest.CityId, orderRequest.CityName, orderRequest.DistrictId, orderRequest.DistrictName,orderRequest.Address, orderRequest.Mobile, orderRequest.Phone, orderRequest.Email,orderRequest.PaymentMethodId, orderRequest.PaymentMethodName, orderRequest.ExpressId,orderRequest.ExpressName, orderRequest.Freight, orderRequest.CouponId, orderRequest.CouponName, orderRequest.CouponValue, orderRequest.OrderTime);foreach (var orderItemRequest in orderRequest.OrderItems){order.AddOrderItem(orderItemRequest.ProductId, orderItemRequest.Quantity, orderItemRequest.UnitPrice, orderItemRequest.JoinedMultiProductsPromotionId, orderItemRequest.ProductName);}DomainRegistry.OrderRepository().Save(order);DomainEventBus.Instance().Publish(new OrderCreated(order.ID, order.UserId, order.Receiver));return Result.Success();}

  不知道大家有沒有發(fā)現(xiàn)這里代碼上的一個(gè)問題,就是DomainEventBus.Instance().Publish()方法在聚合的Save操作之后進(jìn)行,其實(shí)本身不是很符合DDD的概念,任何的領(lǐng)域事件都是基于一個(gè)領(lǐng)域?qū)ο蟮?#xff0c;沒有領(lǐng)域?qū)ο蠛蝸眍I(lǐng)域事件,所以領(lǐng)域事件一般都是由領(lǐng)域?qū)ο髢?nèi)部產(chǎn)生,故這里應(yīng)該要把DomainEventBus.Instance().Publish()方法搬到Order.Create中調(diào)用。如果發(fā)現(xiàn)這個(gè)問題的童鞋,恭喜你對(duì)于領(lǐng)域事件的理解已經(jīng)又深入了一個(gè)層次了。好了上篇中這么寫其實(shí)是為了凸顯出本地?cái)?shù)據(jù)修改提交和領(lǐng)域事件的發(fā)布是涉及到數(shù)據(jù)一致性的問題的,其中的問題是:

  1.如果領(lǐng)域事件發(fā)布出現(xiàn)異常了怎么辦?

  2.如果訂閱者處理出現(xiàn)異常了怎么辦?

  本篇我們就來一個(gè)一個(gè)解決問題。

?

三、本地的一致性

  在解決上面的2個(gè)問題之前,我們先需要考慮在修改多個(gè)聚合的場(chǎng)景下本地上下文內(nèi)的一致性問題,這個(gè)職責(zé)在DDD中由工作單元(UnitOfWork)來負(fù)責(zé),工作單元就是為了保證本地的事務(wù)一致性,在.Net里的實(shí)現(xiàn)一般就是對(duì)SqlTransaction的封裝運(yùn)用。關(guān)于工作單元的實(shí)現(xiàn)一般有2種方式:

  (1)完全依賴于SqlTransaction,在工作單元第一次運(yùn)用的時(shí)候就開啟數(shù)據(jù)庫事務(wù)。

  (2)使用本地變量存儲(chǔ)變動(dòng)的聚合,然后在工作單元Commit()的時(shí)候開啟數(shù)據(jù)庫事務(wù)并寫入。

  2個(gè)實(shí)現(xiàn)方案各有優(yōu)缺點(diǎn),需要在一致性和性能之間做出權(quán)衡。另外工作單元和領(lǐng)域事件發(fā)布的結(jié)合運(yùn)用可以參考我之前寫的2篇文章:DDD設(shè)計(jì)中的Unitwork與DomainEvent如何相容?和DDD中的Unitwork與DomainEvent如何相容?(續(xù)),注意的是我在這2篇中運(yùn)用的是方式(2)的實(shí)現(xiàn)方式。秉著沒有最好只有更好的精神,如何才能做到更好的一致性,這里需要引出幾個(gè)架構(gòu)層面的概念:ES、Saga、A+ES。這些內(nèi)容有一篇蟋蟀兄的文章(傳送門在此)講的很好,推薦大家閱讀一下,我就不展開講這些內(nèi)容了。里面每一種方案的運(yùn)用都有成本,大家根據(jù)實(shí)際情況權(quán)衡再運(yùn)用即可,切記:軟件開發(fā)中沒有銀彈。

?

四、領(lǐng)域事件發(fā)布出現(xiàn)異常

  這個(gè)現(xiàn)象是否會(huì)出現(xiàn)需要根據(jù)領(lǐng)域事件發(fā)布的實(shí)現(xiàn)方式來決定,只要實(shí)現(xiàn)方式是“非本地”的方案,那么必然會(huì)出現(xiàn)一些異常的狀況。假如領(lǐng)域事件是通過消息隊(duì)列來實(shí)現(xiàn),那么涉及到了網(wǎng)絡(luò)傳輸必然會(huì)大大的增加出現(xiàn)異常的可能性。如何來解決此類問題,秉承著一圖勝千言的思想我直接貼個(gè)思維導(dǎo)圖,先看下一般的幾種實(shí)現(xiàn)方案的特點(diǎn),見圖1:

                             【圖1】

  根據(jù)這個(gè)圖,我們發(fā)現(xiàn)魚和熊掌不可兼得,每個(gè)方案都由各自的特點(diǎn),我們應(yīng)當(dāng)根據(jù)不同的場(chǎng)景使用不同的實(shí)現(xiàn)方案去做,才是最好的選擇,并且據(jù)我所知,目前支持事務(wù)的消息隊(duì)列開源方案非常的少,所以我們需要通過一定的補(bǔ)償機(jī)制來處理與消息隊(duì)列通信出現(xiàn)問題的場(chǎng)景。另外在分布式系統(tǒng)中,服務(wù)端的接口設(shè)計(jì)盡量需要滿足無狀態(tài)和冪等性(不展開去講了,大家自行百度或者google),這也是整個(gè)系統(tǒng)高可用的重要的一環(huán)。最后的最后,通過對(duì)賬機(jī)制作為最后一道防線,確保重要的數(shù)據(jù)不產(chǎn)生差錯(cuò)。

  那么我們來看一下這2個(gè)實(shí)現(xiàn)方案對(duì)應(yīng)我們的編碼應(yīng)該如何來做:

  1.通過消息機(jī)制的發(fā)布就是把我在Demo中運(yùn)用DomainEventBus的內(nèi)部實(shí)現(xiàn)由Dictionary替換為外部的消息隊(duì)列即可,然后需要注冊(cè)DistributeExceptionEvent來處理丟給消息隊(duì)列進(jìn)行分發(fā)時(shí)出現(xiàn)異常的問題,做補(bǔ)償措施。

  2.通過DB的方案,大致的偽代碼如下:

var unitOfWork = new UnitOfWork();unitOfWork.RegisterSaved(order);var domainEvents = GetEventsFromBus();foreach(var domainEvent in domainEvents){var body = Serialize(domainEvent);unitOfWork.RegisterSaved(new Message{Body = body});}return unitOfWork.Commit();

  大家可以看到,這個(gè)方式首先帶來的問題是讓工作單元變得異常的臃腫,隨之導(dǎo)致整個(gè)事務(wù)的總耗時(shí)增加。并且此時(shí)Message表中的現(xiàn)存數(shù)據(jù)可能還在同步進(jìn)行消費(fèi)/推送,那么產(chǎn)生資源競(jìng)爭(zhēng)是必然會(huì)遇到的問題,導(dǎo)致的后果是整個(gè)工作單元的提交失敗。

?

五、訂閱者處理出現(xiàn)異常

  這個(gè)問題也是比較常見的,特別是處理業(yè)務(wù)復(fù)雜的接口和涉及過多RPC調(diào)用的接口出現(xiàn)的概率更大。所以每個(gè)應(yīng)用每個(gè)接口都需要考慮好此類問題。一般的解決方案我也梳理了一個(gè)思維導(dǎo)圖,如下圖2:

                              【圖2】

  其實(shí)很明顯通過回滾的方式有很多局限性。所以說個(gè)人建議選擇下面的方案,盡量做到內(nèi)部消化,以提高接口對(duì)外的自治性。另外針對(duì)重試進(jìn)行一些限制,一是為了減少一些無用功來占用系統(tǒng)資源,二是避免在系統(tǒng)本身達(dá)到瓶頸的情況下出現(xiàn)馬太效應(yīng),讓擁堵問題越發(fā)嚴(yán)重。

?

六、結(jié)語

  本篇沒有增加太多代碼,只是在Mall.Infrastructure中增加了幾個(gè)工作單元(方式(2))相關(guān)的類,其中只包含了一些核心邏輯代碼,具體的實(shí)現(xiàn)希望大家能夠自己動(dòng)手。多謝各位看官。

?

?

?

本文完整的源碼地址:https://github.com/ZacharyFan/DDDDemo/tree/Demo13。

?

作者:Zachary_Fan
出處:http://www.cnblogs.com/Zachary-Fan/p/DDD_13.html

?

?

?關(guān)于作者:張帆(Zachary,個(gè)人微信號(hào):Zachary-ZF)。堅(jiān)持用心打磨每一篇高質(zhì)量原創(chuàng)。歡迎掃描右側(cè)的二維碼~。

定期發(fā)表原創(chuàng)內(nèi)容:架構(gòu)設(shè)計(jì)丨分布式系統(tǒng)丨產(chǎn)品丨運(yùn)營(yíng)丨一些思考。

?

如果你是初級(jí)程序員,想提升但不知道如何下手。又或者做程序員多年,陷入了一些瓶頸想拓寬一下視野。歡迎關(guān)注我的公眾號(hào)「跨界架構(gòu)師」,回復(fù)「技術(shù)」,送你一份我長(zhǎng)期收集和整理的思維導(dǎo)圖。

如果你是運(yùn)營(yíng),面對(duì)不斷變化的市場(chǎng)束手無策。又或者想了解主流的運(yùn)營(yíng)策略,以豐富自己的“倉庫”。歡迎關(guān)注我的公眾號(hào)「跨界架構(gòu)師」,回復(fù)「運(yùn)營(yíng)」,送你一份我長(zhǎng)期收集和整理的思維導(dǎo)圖。

轉(zhuǎn)載于:https://www.cnblogs.com/Zachary-Fan/p/DDD_13.html

總結(jié)

以上是生活随笔為你收集整理的如何一步一步用DDD设计一个电商网站(十三)—— 领域事件扩展的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 初尝黑人巨炮波多野结衣 | 欧美成人aaaa | 日本一区二区不卡在线观看 | 日韩一级黄色大片 | 麻豆视频免费在线观看 | 久久大胆视频 | 污视频免费在线观看网站 | 看黄色大片 | 在线黄色av网站 | 久久人人爽人人爽人人片亚洲 | 天天综合亚洲 | 精品无码免费视频 | 欧美视频久久 | 国产免费一区 | 成年人在线免费观看视频网站 | 精品国产自| 免费午夜视频在线观看 | av字幕网| 亚洲爽爽 | 亚洲视频 一区 | 美女在线免费视频 | 动漫av在线免费观看 | 欧美 亚洲 另类 偷偷 自拍 | 男人操女人免费 | xxxwww18| 极品少妇xxx | 97人人爽人人爽人人爽 | 亚洲人精品 | 日韩欧美国产三级 | 免费日皮视频 | 爽爽窝窝午夜精品一区二区 | 国产精品1页 | 国产成人精品一区二区三区福利 | 久草电影在线 | 97精品一区二区三区 | 熟女一区二区三区视频 | 日韩精品一区在线播放 | 精品熟妇无码av免费久久 | 99久久婷婷国产一区二区三区 | 久操视频免费看 | 日韩av一区二区三区四区 | 内裤摩擦1v1h | 人妻无码一区二区三区 | 无码成人精品区在线观看 | 尤物视频在线看 | 星空大象在线观看免费播放 | 操你啦在线视频 | 欧洲亚洲一区二区 | 日韩视频在线播放 | 又色又爽又黄无遮挡的免费视频 | 国产精品igao视频 | 亚洲无人区码一码二码三码的含义 | 污污网站在线播放 | 天天草影院 | 欧美日韩丝袜 | 亚洲国产99| 亚洲一区激情 | 亚洲精品社区 | 成人做爰www免费看视频网站 | 老湿机69福利区午夜x片 | 91av毛片| 黄色片a级片 | 少妇高潮露脸国语对白 | gav在线| 日韩av毛片在线观看 | av免费观看网站 | 国产日 | 91se在线| 欧美精品色婷婷五月综合 | 无限资源日本好片 | 无码人中文字幕 | 亚洲天堂福利 | 亚洲AV无码成人精品区明星换面 | 涩涩涩在线视频 | 中文在线国产 | 国产深夜福利在线 | 精品国产免费人成在线观看 | 少妇床戏av | 永久精品 | 国产精品jizz在线观看美国 | 成人在线免费网站 | 欧美久久久久久 | 超碰一区二区 | 亚洲aa| 天堂网在线中文 | 亚洲欧美在线综合 | 欧美黑人又粗又大又爽免费 | 国产三级一区二区 | 国产一区二区三区视频在线播放 | 日韩在线观看视频一区 | 国产成人8x视频一区二区 | 国产成人精品无码免费看夜聊软件 | 涩涩涩涩涩涩涩涩涩涩 | 绿帽h啪肉np辣文 | 91网址在线观看 | 成年人在线播放 | 久久久精品久久久久久 | 亚洲高清在线播放 | 日本中文字幕在线看 |