日韩性视频-久久久蜜桃-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ò),歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 久久伊人免费 | 人人干人人插 | 亚洲av成人片无码 | 男女做爰猛烈吃奶啪啪喷水网站 | 日韩有码一区 | 久插网| 美女福利影院 | 免费日韩在线视频 | 色眯眯影视 | 国产永久免费观看 | 波多野结衣av中文字幕 | 国产剧情自拍 | 黄网在线观看视频 | 国产原创在线 | 日韩电影中文字幕 | 精品+无码+在线观看 | 国产天天操 | 久久www视频 | 欧美做爰啪啪xxxⅹ性 | 久久视频黄色 | 超碰成人免费在线 | 无码一区二区三区 | 九九久久视频 | av大片网址| 超碰xxx| 国产视频第一区 | 免费高清毛片 | 黑人av | 国产福利三区 | 91精品国产自产精品男人的天堂 | 91成人免费视频 | 亚洲AV无码一区二区三区蜜桃 | 午夜网站在线观看 | 91大神小宝寻花在线观看 | 日韩av色| 毛片自拍 | chinese中国性按摩hd | 亚洲码无人客一区二区三区 | 亚洲一区二区三区四 | xxx.国产| 免费无码又爽又黄又刺激网站 | 国产怡红院| 日韩亚洲国产精品 | 日本在线高清 | 黄色高清免费 | 男生插女生网站 | 美女在线观看视频 | 日日干日日爽 | 五月天色丁香 | 欧美美女一区二区 | 黄在线网站 | 亚洲日本中文字幕 | 黄色无遮挡网站 | 久久这里只有精品首页 | 一区二区三区在线视频播放 | 丰满尤物白嫩啪啪少妇 | 欧美黑粗硬| 伊人99在线 | 性自由色xxxx免费视频 | 成人无码视频 | 久草免费av | 中文在线视频观看 | 日本精品在线观看视频 | 天天做天天摸天天爽天天爱 | 中文字幕国产一区二区 | 亚洲欧美乱日韩乱国产 | 国产福利在线导航 | 日韩操操操 | 国产欧美一区二区三区视频 | av三级在线观看 | 一本久道久久综合无码中文 | 人妻少妇偷人精品久久性色 | 超碰免费在线97 | 免费观看黄色一级视频 | 久久av红桃一区二区小说 | 亚洲欧美一区二区视频 | 1000部啪啪未满十八勿入超污 | 一区二区三区在线视频免费观看 | 亚洲激情综合网 | 在线免费观看欧美大片 | 手机在线观看av | 日本黄视频在线观看 | 国产成人手机在线 | 欧美少妇诱惑 | 福利视频一区二区 | 亚洲AV无码一区二区三区性 | 午夜福利视频一区二区 | 伊人久久久久久久久久久 | www.插插 | 97久久人澡人人添人人爽 | 一级α片免费看刺激高潮视频 | 超碰女人 | av手机天堂 | 99精品一级欧美片免费播放 | 少妇被按摩师摸高潮了 | 特一级黄色片 | a国产免费 | 欧美黑人做爰爽爽爽 | 在线免费观看成年人视频 |