??xml version="1.0" encoding="utf-8" standalone="yes"?>国产精品毛片久久久久久久久久99999999 ,日韩欧美国产精品,久久精品最新地址http://www.aygfsteel.com/paulwong/category/55163.htmlzh-cnThu, 25 Feb 2021 21:42:33 GMTThu, 25 Feb 2021 21:42:33 GMT60领域驱动设计实战http://www.aygfsteel.com/paulwong/archive/2021/02/25/435811.htmlpaulwongpaulwongThu, 25 Feb 2021 07:53:00 GMThttp://www.aygfsteel.com/paulwong/archive/2021/02/25/435811.htmlhttp://www.aygfsteel.com/paulwong/comments/435811.htmlhttp://www.aygfsteel.com/paulwong/archive/2021/02/25/435811.html#Feedback0http://www.aygfsteel.com/paulwong/comments/commentRss/435811.htmlhttp://www.aygfsteel.com/paulwong/services/trackbacks/435811.html领域驱动QDDDQDomain Driven DesignQؓ(f)软g设计提供了一套完整的理论指导和落地实践,通过战略设计和战术设计,技术实C业务逻辑分离Q来应对复杂的Y件系l。本pd文章准备以实战的角度来介l?DDDQ首先编写领域驱动的代码模型Q然后再Z代码模型Q引?DDD 的各Ҏ(gu)念,先介l战术设计,再介l战略设计?/p>

DDD 实战1 - 基础代码模型
DDD 实战2 - 集成限界上下文(Rest & DubboQ?/a>
> DDD 实战3 - 集成限界上下文(消息模式Q?br />> DDD 实战4 - 领域事g的设计与使用
> DDD 实战5 - 实体与值对?br />> DDD 实战6 - 聚合的设?br />> DDD 实战7 - 领域工厂与领域资源库
> DDD 实战8 - 领域服务与应用服?br />> DDD 实战9 - 架构设计
> DDD 实战10 - 战略设计



paulwong 2021-02-25 15:53 发表评论
]]>
DDD领域驱动设计 - 设计文模板http://www.aygfsteel.com/paulwong/archive/2017/02/19/432319.htmlpaulwongpaulwongSun, 19 Feb 2017 04:14:00 GMThttp://www.aygfsteel.com/paulwong/archive/2017/02/19/432319.htmlhttp://www.aygfsteel.com/paulwong/comments/432319.htmlhttp://www.aygfsteel.com/paulwong/archive/2017/02/19/432319.html#Feedback0http://www.aygfsteel.com/paulwong/comments/commentRss/432319.htmlhttp://www.aygfsteel.com/paulwong/services/trackbacks/432319.html设计文模板Q?/h3>
  1. pȝ背景和定?/li>
  2. 业务需求描q?/li>
  3. 领域语言整理Q主要是整理领域中的各种术语的定义,名词解释
  4. 领域划分Q分析出子域、核心域、支撑域Q?/li>
  5. pȝ用例?/li>
  6. 每个子域的领域模型设计(实体、值对象、聚合、领域事Ӟ需要注意的是:(x)领域模型是需要抽象的Q要分析业务本质Q而不是简单的直接寚w求进行徏模)
  7. 领域模型详细说明Q如Z么这栯计的原因、模型内对象的关pR各U业务规则、数据一致性规则等Q?/li>
  8. 领域服务、仓储、工厂设?/li>
  9. Saga业务程设计
  10. 关键聚合根的状态流转图
  11. 场景走查Q讲q如何通过领域模型、领域服务、仓储、Saga程{完成系l用例以?qing)关键业务流E的Q?/li>
  12. 架构设计Q如传统三层架构、经典四层架构、CQRS/ES架构Q?/li>

一些其他的思考:(x)

  • 去除一切花俏的建模技巧,我觉得最重要的方向就是去努力分析问题和事物的本质Q针对这个本质进行领域徏模。这个领域徏模,最主要的还是锻炼的人的事物抽象能力?0个hQ徏出来的领域模型都不同。本质原因就是大家对同一个问题的理解不同Q对事物的本质的理解不同。虽然最l都能解军_前的问题Q但是对适应未来需求变化的能力却是不同?/li>
  • 所以,我们要把旉花在多理解业务上Q让自己成ؓ(f)领域专家Q只有这P才能充分理解业务。多理解一点业务,你才能更好的抽象Z务本质背后的领域模型。很有做到很快理解业务Qƈ很快针对业务设计出正的领域模型Q至我是不行?/li>
  • 领域建模需要时_(d)是一个P代的q程Qh无完人。而时间很多时候也不会(x)很充I所以,不太可能一步到位把领域设计做的很完。我们在整体目规划的时候可能会(x)有个大的架构设计、业务大图(边界思维Q,但是不可能达到领域设计的_度Q只能是一期一期的完善Q到最后可能才?x)有完整的上面的目录内容。每一期都需要考虑支持的场景约束、上下文、系l边界、持l集成的相关设计。设计product, not project?/li>


paulwong 2017-02-19 12:14 发表评论
]]>
谈我对DDD领域驱动设计的理??http://www.aygfsteel.com/paulwong/archive/2017/02/19/432318.htmlpaulwongpaulwongSun, 19 Feb 2017 04:12:00 GMThttp://www.aygfsteel.com/paulwong/archive/2017/02/19/432318.htmlhttp://www.aygfsteel.com/paulwong/comments/432318.htmlhttp://www.aygfsteel.com/paulwong/archive/2017/02/19/432318.html#Feedback0http://www.aygfsteel.com/paulwong/comments/commentRss/432318.htmlhttp://www.aygfsteel.com/paulwong/services/trackbacks/432318.html从遇到问题开?/h2>

当h们要做一个Y件系l时Q一般L因ؓ(f)遇到了什么问题,然后希望通过一个Y件系l来解决?/p>

比如Q我是一家企业,然后我觉得我现在U下销售自q产品q不够,我希望能够在U上也能销售自q产品。所以,自然而然想到要做一个普通电(sh)商系l,用于实现在线销售自׃业品的目的?/p>

再比如,我是一家互联网公司Q公司有很多pȝ对外提供服务Q面向很多客L(fng)讑֤。但是最q由于各U原因,D服务l常出故障。所以,我们希望通过各种措施提高服务的质量和E_性。其中的一个措施就是希望能做一个灰度发布的q_Q这个^台可以提供灰度发布的服务。然后,当某个业务系l做了一些修改ƈ需要发布时Q可以用我们的灰度发布q_来非常方便的实现灰度发布的功能。比如在灰度发布q_上方便的定制允许哪些特定的客L(fng)才会(x)讉K新服务,哪些客户端l用老服务。灰度发布^台可以提供各U灰度的{略。有了这L(fng)灰度发布机制Q那即便pȝ的新逻辑有什么问题,受媄(jing)响的面也不会(x)很大Q在可控范围内。所以,如果公司里的所有对外提供服务的pȝ都接入了灰度q_Q那q些pȝ的发布环节就可以更加有保障了?/p>

MQ我们做M一个Y件系l,都是有原因的Q否则就没必要做q个pȝQ而这个原因就是我们遇到的问题。所以,通过问题Q我们就知道了我们需要一个什么样的系l,q个pȝ解决什么样的问题。最后,我们很自然的得Z一个目标,即知道了自己要什么。比如我要做一个论坛、一个博客系l、一个电(sh)商^台、一个灰度发布系l、一个IDE、一个分布式消息队列、一个通信框架Q等{?/p>

DDD切入? - 理解概念

DDD的全UCؓ(f)Domain-driven DesignQ即领域驱动设计。下面我从领域、问题域、领域模型、设计、驱动这几个词语的含义和联系的角度去阐述DDD是如何融入到我们qx的Y件开发初期阶D늚。要理解什么是领域驱动设计Q首先要理解什么是领域Q什么是设计Q还有驱动是什么意思,什么驱动什么?/p>

什么是领域QDomainQ?

前面我们已经清楚的知道我们现在要做一个什么样的系l,q个pȝ需要解决什么问题。我认ؓ(f)M一个系l都?x)属于某个特定的领域Q比如论坛是一个领域,只要你想做一个论坛,那这个论坛的核心业务是确定的Q比如都有用户发帖、回帖等核心基本功能。比如电(sh)商^台、普通电(sh)商系l,q种都属于网上电(sh)商领域,只要是这个领域的pȝQ那都有商品览、购物R、下单、减库存、付?gu)ƾ交易等核心环节。所以,同一个领域的pȝ都具有相同的核心业务Q因Z们要解决的问题的本质是类似的?/p>

因此Q我们可以推断出Q一个领域本质上可以理解为就是一个问题域Q只要是同一个领域,那问题域q同。所以,只要我们定了系l所属的领域Q那q个pȝ的核心业务,卌解决的关键问题、问题的范围边界基本确定了。通常我们_(d)要成Z个领域的专家Q必要在这个领域深入研I很多年才行。因为只有你研究了很多年Q你才会(x)遇到非常多的该领域的问题Q同时你解决q个领域中的问题的经验也非常丰富。很多时候,领域专家比技术专家更加吃香,比如金融领域的专家?/p>

什么是设计QDesignQ?

DDD中的设计主要指领域模型的设计。ؓ(f)什么是领域模型的设计而不是架构设计或其他的什么设计呢Q因为DDD是一U基于模型驱动开发的软g开发思想Q强调领域模型是整个pȝ的核心,领域模型也是整个pȝ的核心h(hun)值所在。每一个领域,都有一个对应的领域模型Q领域模型能够很好的帮我们解军_杂的业务问题?/p>

从领域和代码实现的角度来理解Q领域模型绑定了领域和代码实玎ͼ保了最l的代码实现׃定是解决了领域中的核心问题的。因为:(x)1Q领域驱动领域模型设计;2Q领域模型驱动代码实现。我们只要保证领域模型的设计是正的Q就能确定领域模型可以解决领域中的核心问题;同理Q我们只要保证代码实现是严格按照领域模型的意图来落地的,那就能保证最后出来的代码能够解决领域的核心问题的。这个思\Q和传统的分析、设计、编码这几个阶段被割裂(q且每个阶段的物也不同Q的软g开发方法学形成鲜明的对比?/p>

什么是驱动QDrivenQ?

上面其实已经提到了,是Q?Q领域驱动领域模型设计;2Q领域模型驱动代码实现。这个就和我们传l的数据库驱动开发的思\形成Ҏ(gu)了。DDD中,我们L以领域ؓ(f)边界Q分析领域中的核心问题(核心x点)Q然后设计对应的领域模型Q再通过领域模型驱动代码实现。而像数据库设计、持久化技术等q些都不是DDD的核心,而是外围的东ѝ?/p>

领域驱动设计QDDDQ告诉我们的最大h(hun)值我觉得是:(x)当我们要开发一个系l时Q应该尽量先把领域模型想清楚Q然后再开始动手编码,q样的系l后期才?x)很好维护。但是,很多目Q尤其是互联|项目,Z赶工Q都是一开始模型没x楚,一上来开始徏表写代码Q代码写的非常冗余,完全是过E是的思考方式,最后导致系l非帔R以维护。而且更糟p的是,出来hL要还的,前期的领域模型设计的不好Q不够抽象,如果你的pȝ?x)长期需要维护和适应业务变化Q那后面你一定会(x)遇到各种问题l护上的困难Q比如数据结构设计不合理Q代码到处冗余,改BUG到处引入新的BUGQ新人对q种代码上手困难Q等。而那时如果你再想重构模型Q那要付出的代h(hun)?x)比一开始重新开发还要大Q因Zq要考虑兼容历史的数据,数据q移Q如何^滑发布等各种头疼的问题。所以,导致我们最后天天加班?/p>

虽然Q我们都知道q个道理Q但是我也明白,人的?fn)惯很难改变的,大部分h都很难从面向q程式的惛_哪里写到哪里的思想转变为基于系l化的模型驱动的思维。我惻Iq或许是DDD很难在中国或国外行h的原因吧。但是,我想q不应该成ؓ(f)我们攑ּ学习(fn)DDD的原因,对吧Q?/p>

概念ȝQ?/h3>
  1. 领域是问题域,有边界,领域中有很多问题Q?/li>
  2. M一个系l要解决的那个大问题都对应一个领域;
  3. 通过建立领域模型来解决领域中的核心问题,模型驱动的思想Q?/li>
  4. 领域建模的目标针Ҏ(gu)们在领域中所兛_的问题,卛_针对核心x点,而不是整个领域中的所有问题;
  5. 领域模型在设计时应考虑一定的抽象性、通用性,以及(qing)复用价|
  6. 通过领域模型驱动代码的实玎ͼ保代码让领域模型落圎ͼ代码最l能解决问题Q?/li>
  7. 领域模型是系l的核心Q是领域内的业务的直接沉淀(wn)Q具有非常大的业务h(hun)|
  8. 技术架构设计或数据存储{是在领域模型的外围Q帮助领域模型进行落圎ͼ

DDD切入? - 理解领域、拆分领域、细化领?/h2>

理解领域知识是基

上面我们通过W一步,虽然我们明确了要做一个什么样的系l,该系l主要解决什么问题,但是ph们还无法开始进行实际的需求分析和模型设计Q我们还必须我们的问题q行拆分Q需求进行细化。有些时候,需求方Q即提出问题的hQ很可能自己不清楚具体想要什么。他只知道一个概念,一个大的目标。比如他只知道要做一个股交易系l,一个灰度发布系l,一个电(sh)商^収ͼ一个开发工P{。但是他不清楚这些系l应该具体做成什么样子。这个时候,我认为领域专家就非常重要了,DDD也非常强调领域专家的重要性。因为领域专家对q个领域非常了解Q对领域内的各种业务场景和各U业务规则也非常清楚QMQ对q个领域内的一切业务相关的知识都非怺解。所以,他们自然有能力表达出系l该做成什么样子。所以,要知道一个系l到底该做成什么样子,到底哪些是核心业务关注点Q只能靠沉淀(wn)领域内的各种知识Q别无他法。因此,假设你现在打做一个电(sh)商^収ͼ但是你对q个领域没什么了解,那你一定得先去了解下该领域内主的?sh)商q_Q比如淘宝、天猫、京东、亚马逊等。这个了解的q程是你沉淀(wn)领域知识的过E。如果你不了解,q你领域徏模的能力再强Q各U技术架构能力再Z是不上力。领域专家不是某个固定的角色Q而是某一cMhQ这cMh对这个领域非怺解。比如,一个开发h员也可以是一个领域专家。假设你在一个公司开发和l护一个系l已l好几年了,但是q个pȝ的品经理(PDQ可能已l换q好几Q了,q种情况下,我相信这几Q产品l理都没有比你更熟?zhn)q个领域?/p>

拆分领域

上面我们明白了,领域建模的基是要先理解领域,让自己成为领域专家。如果做Cq点Q我们就打好了坚实的基础了。但是,有时一个领域往往太复杂,涉及(qing)到的领域概念、业务规则、交互流E太多,D我们没办法直接针对这个大的领域进行领域徏模。所以,我们需要将领域q行拆分Q本质上是把大问题拆分为小问题Q然后各个击破的思\。然后既然把一个大的领域划分ؓ(f)了多个小的领域(子域Q,那最关键的就是要理清每个子域的边界;然后要搞清楚哪些子域是核心子域,哪些是非核心子域Q哪些是公共支撑子域Q然后,q要思考子域之间的联系是什么。那么,我们该如何划分子域呢Q我的个人看法是从业务相x的角度L考,也就是我们^时说的按业务功能为出发点q行划分。还是拿l典的电(sh)商系l来分析Q通常一个电(sh)商系l都?x)包含好几个大块Q比如:(x)

  • ?x)员中心Q负责用戯̎L(fng)录、用户信息的理Q?/li>
  • 商品中心Q负责商品的展示、导航、维护;
  • 订单中心Q负责订单的生成和生命周期管理;
  • 交易中心Q负责交易相关的业务Q?/li>
  • 库存中心Q负责维护商品的库存Q?/li>
  • 促销中心Q负责各U促销zd的支持;

上面q些中心看v来很自然Q因为大家对?sh)子商务的这个领域都已经非常熟(zhn)了,所以都没什么疑问,好像很自然的样子。所以,领域划分是不是就是没什么挑战了呢?昄不是。之所以我们觉得子域划分很单,是因为我们对整个大领域非怺解了。如果我们遇C个冷门的领域Q就没办法这么容易的d分子域了。这需要我们先d力理解领域内的知识。所以,我个Z来不怿什么子域划分的技巧什么的东西Q因为我觉得q个工作没有M诀H可以用。当我们不了解一个东西的时候,如何L解它Q当我们Ҏ(gu)个领域有一定的熟?zhn)了,了解了领域内的相关业务的本质和关p,我们p然而然的能划分出合理的子域了。不qƈ不是所有的pȝ都需要划分子域的Q有些系l只是解决一个小问题Q这个问题不复杂Q可能只有一两个核心概念。所以,q种pȝ完全不需要再划分子域。但不是l对的,当一个领域,我们的关注点来多Q每个关注点我们x的信息越来越多的时候,我们?x)不pȝ去进一步的划分子域。比如,也许我们一开始将商品和商品的库存都放在商品中心里Q但是后来由于库存的l护来复杂,D揉在一起对我们的系l维护带来一定的困难Ӟ我们׃(x)考虑两者进行拆分,q个是所谓的业务垂直分割?/p>

l化子域

通过上面的两步,我们了解了领域里的知识,也对领域q行了子域划分。但q样q不够,凭这些我们还无法q行后箋的领域模型设计。我们还必须再进一步细化每个子域,q一步明每个子域的核心x点,即需求细化。我觉得我们需要细化的斚w有以下几点:(x)

  1. 梳理领域概念Q梳理出领域内我们关注的概念、概늚关系Qƈl一交流词汇QŞ成统一语言Q?/li>
  2. 梳理业务规则Q梳理出领域内我们关注的各种业务规则QDDD中叫不变性(invariantsQ,比如唯一性规则,余额不能于零等Q?/li>
  3. 梳理业务场景Q梳理出领域内的核心业务场景Q比如电(sh)商^C的加入购物R、提交订单、发起付?gu)Ƅ核心业务场景Q?/li>
  4. 梳理业务程Q梳理出领域内的关键业务程Q比如订单处理流E,退ƾ流E等Q?/li>

从上面这4个方面,我们从领域概c(din)业务规则、交互场景、业务流E等l度梳理了我们到底要什么,整理了整个系l应该具备的功能。这个工作我觉得是一个非常具有创造性和有难度的工作。我们一斚w?x)主观的定义我们惌什么;另一斚wQ我们还?x)思考我们要的东西的合理性。我认ؓ(f)q个是产品l理的工作,产品l理必须要负赯责,把他的品充分设计好Q从各个斚w去考虑Q如何设计一个品,才能更好的解决用L(fng)核心诉求Q即领域内的核心问题。如果对领域不够了解Q如果想不清楚用户到底要什么,如果思考问题不够全面,谈何设计Z个合理的产品呢?

关于领域概念的梳理,我觉得可以采用四色原型分析法Q这个分析法通过pȝ的方法,概念划分ؓ(f)不同的种c,Z同种cȝ概念标注不同的颜艌Ӏ然后将q些概念有机的组合v来,从而让我们可以清晰的分析出概念和概念之间的关系。有兴趣的同学可以在|上搜烦(ch)?a target="_blank" style="color: #1d58d1; text-decoration: none;">四色原型?/p>

注意Q上面我说的q四点,重点是梳理出我们要什么功能,而不是思考如何实现这些功能,如何实现是Y件设计h员的职责?/strong>

DDD切入? - 领域模型设计

q部分内容,我想学习(fn)DDD的h都很熟?zhn)了。DDD原著中提Z很多实用的徏模工P(x)聚合、实体、值对象、工厂、仓储、领域服务、领域事件。我们可以用这些工P来设计每一个子域的领域模型。最l通过领域模型囑ְ设计沉淀(wn)下来。要使用q些工具Q首先就要理解每个工L(fng)含义和用场景。不要以为很单哦Q比如聚合的划分是一个非常具有艺术的zR同一个系l,不同的h设计出来的聚合是完全不同的。而且很有可能高手之间的最后设计出来的差别反而更大,实际上我认ؓ(f)是世界观的相互碰撞,呵呵。所以,要领域徏模,我觉得每个h都应该去学学哲学知识Q这有助于我们更好的认识世界Q更好的理解事物的本质?/p>

关于q些建模工具的概念和如何q用我就不多展开了,我博客里也有很多q方面的介绍。下面我再讲一下我认ؓ(f)比较重要的东西,比如到底该如何领域徏模?步骤应该是怎么L(fng)Q?/p>

领域建模的方?/h3>

通过上面我介l的l化子域的内容,现在再来谈该如何领域建模Q我觉得方便很多了。我的主要方法是Q?/p>

  1. 划分好边界上下文Q通常每个子域Qsub domainQ对应一个边界上下文Qbounded contextQ,同一个边界上下文中的概念是明的Q没有Q何歧义;
  2. 在每个边界上下文中设计领域模型,具体的领域模型设计方法有很多U,如以场景为出发点?a target="_blank" style="color: #1d58d1; text-decoration: none;">四色原型分析法,或者我早期写的q篇文章Q这个步骤最核心的就是找合根Qƈ扑և每个聚合根包含的信息Q关于如何设计聚合,可以看一下我写的q篇文章Q?/li>
  3. d领域模型图,圈出每个模型中的聚合边界Q?/li>
  4. 设计领域模型Ӟ要考虑该领域模型是否满业务规则,同时q要l合考虑技术实现等问题Q比如ƈ发问题;领域模型不是概念模型Q概忉|型不x技术实玎ͼ领域模型兛_Q所以领域模型才能直接指导编码实玎ͼ
  5. 思考领域模型是如何在业务场景中发挥作用的,以及(qing)是如何参与到业务程的每个环节的Q?/li>
  6. 场景走查Q确认领域模型是否能满领域中的业务场景和业务流E;
  7. 模型持箋重构、完善、精|

领域模型的核心作用:(x)

  1. 抽象了领域内的核心概念,q徏立概念之间的关系Q?/li>
  2. 领域模型承担了领域内的状态的l护Q?/li>
  3. 领域模型l护了领域内的数据之间的业务规则Q数据一致性;

下图是我最q做个一个普通电(sh)商系l的商品中心的领域模型图Q给大家参考:(x)

领域模型设计只是软g设计中的一部?/h3>

需要特别注意的是,领域模型设计只是整个软g设计中的很小一部分。除了领域模型设计之外,要落C个系l,我们q有非常多的其他设计要做Q比如:(x)

  • 定w规划
  • 架构设计
  • 数据库设?/li>
  • ~存设计
  • 框架选型
  • 发布Ҏ(gu)
  • 数据q移、同步方?/li>
  • 分库分表Ҏ(gu)
  • 回滚Ҏ(gu)
  • 高ƈ发解x?/li>
  • 一致性选型
  • 性能压测Ҏ(gu)
  • 监控报警Ҏ(gu)

{等。上面这些都需要我们^时的大量学习(fn)和积累。作Z个合格的开发h员或架构师,我觉得除了要?x)DDD领域驱动设计Q还要会(x)上面q么多的技术能力,实是非怸Ҏ(gu)的。所以,千万不要以ؓ(f)?x)DDD了就以ؓ(f)自己很牛|实际上你?x)的只是软g设计中的冰山一角而已?/p>

ȝ

本文的重Ҏ(gu)Z我个人对DDD的一些理解,希望能整理出一些自己ȝ出来的一些感(zhn)和l验Qƈ分nl大家。我怿很多人已l看q太多DDD书上的东西,我L感觉书上的东西看似都?#8221;正规“Q很多时候我们读了之后很难消化,q理解了书里的内容Q当我们惌q用到实践中ӞL感觉无从下手。本文希望通过通俗易懂的文字,介绍了一部分我对DDD的学?fn)感?zhn)和实践心得Q希望能l大家一些启发和帮助?/p>

paulwong 2017-02-19 12:12 发表评论
]]>DDD CQRS架构和传l架构的优缺Ҏ(gu)?/title><link>http://www.aygfsteel.com/paulwong/archive/2017/02/19/432316.html</link><dc:creator>paulwong</dc:creator><author>paulwong</author><pubDate>Sun, 19 Feb 2017 00:39:00 GMT</pubDate><guid>http://www.aygfsteel.com/paulwong/archive/2017/02/19/432316.html</guid><wfw:comment>http://www.aygfsteel.com/paulwong/comments/432316.html</wfw:comment><comments>http://www.aygfsteel.com/paulwong/archive/2017/02/19/432316.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/paulwong/comments/commentRss/432316.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/paulwong/services/trackbacks/432316.html</trackback:ping><description><![CDATA[最q几q_(d)在DDD的领域,我们l常?x)看到CQRS架构的概c(din)我个h也写了一个ENode框架Q专门用来实现这个架构。CQRS架构本n的思想其实非常单,是d分离。是一个很好理解的思想。就像我们用MySQL数据库的dQ数据写CQ然后查询从备来查,d数据的同步由MySQL数据库自p责,q是一U数据库层面的读写分R关于CQRS架构的介l其实已l非常多了,大家可以自行癑ֺ或google。我今天主要xȝ一下这个架构相对于传统架构Q三层架构、DDDl典四层架构Q在数据一致性、扩展性、可用性、׾~性、性能q几个方面的异同Q希望可以ȝZ些优点和~点Qؓ(f)大家在做架构选型时提供参考?br /><br />前言<br /><br />CQRS架构׃本n只是一个读写分ȝ思想Q实现方式多U多栗比如数据存储不分离Q仅仅只是代码层面读写分,也是CQRS的体玎ͼ然后数据存储的读写分,C端负责数据存储,Q端负责数据查询,Q端的数据通过C端生的Event来同步,q种也是CQRS架构的一U实现。今天我讨论的CQRS架构是指这U实现。另外很重要的一点,C端我们还?x)引入Event Sourcing+In Memoryq两U架构思想Q我认ؓ(f)q两U思想和CQRS架构可以完美的结合,发挥CQRSq个架构的最大h(hun)倹{?br /><br />数据一致?br /><br />传统架构Q数据一般是Z致性的Q我们通常?x)用数据库事务保证一ơ操作的所有数据修攚w在一个数据库事务里,从而保证了数据的强一致性。在分布式的场景Q我们也同样希望数据的强一致性,是使用分布式事务。但是众所周知Q分布式事务的难度、成本是非常高的Q而且采用分布式事务的pȝ的吞吐量都会(x)比较低,pȝ的可用性也?x)比较低。所以,很多时候,我们也会(x)攑ּ数据的强一致性,而采用最l一致性;从CAP定理的角度来_(d)是攑ּ一致性,选择可用性?br /><br />CQRS架构Q则完全U持最l一致性的理念。这U架构基于一个很重要的假设,是用户看到的数据L旧的。对于一个多用户操作的系l,q种现象很普遍。比如秒杀的场景,当你下单前,也许界面上你看到的商品数量是有的Q但是当你下单的时候,pȝ提示商品卖完了。其实我们只要仔l想惻I也确实如此。因为我们在界面上看到的数据是从数据库取出来的,一旦显C到界面上,׃?x)变了。但是很可能其他人已l修改了数据库中的数据。这U现象在大部分系l中Q尤其是高ƈ发的WEBpȝQ尤其常见?br /><br />所以,Zq样的假设,我们知道Q即便我们的pȝ做到了数据的Z致性,用户q是很可能会(x)看到旧的数据。所以,q就l我们设计架构提供了一个新的思\。我们能否这样做Q我们只需要确保系l的一切添加、删除、修Ҏ(gu)作所Z的数据是最新的Q而查询的数据不必是最新的。这样就很自然的引出了CQRS架构了。C端数据保持最新、做到数据强一_(d)Q端数据不必最斎ͼ通过C端的事g异步更新卛_。所以,Zq个思\Q我们开始思考,如何具体的去实现CQ两端。看到这里,也许你还有一个疑问,是ZC端的数据是必要最新的Q这个其实很Ҏ(gu)理解Q因Z要修Ҏ(gu)据,那你可能?x)有一些修改的业务规则判断Q如果你Z的数据不是最新的Q那意味着判断失L义或者说不准,所以基于老的数据所做的修改是没有意义的?br /><br />扩展?br /><br />传统架构Q各个组件之间是Z赖,都是对象之间直接Ҏ(gu)调用Q而CQRS架构Q则是事仉动的思想Q从微观的聚合根层面Q传l架构是应用层通过q程式的代码协调多个聚合根一ơ性以事务的方式完成整个业务操作。而CQRS架构Q则是以Saga的思想Q通过事g驱动的方式,最l实现多个聚合根的交互。另外,CQRS架构的CQ两端也是通过事g的方式异步进行数据同步,也是事g驱动的一U体现。上升到架构层面Q那前者就是SOA的思想Q后者是EDA的思想。SOA是一个服务调用另一个服务完成服务之间的交互Q服务之间紧耦合QEDA是一个组件订阅另一个组件的事g消息Q根据事件信息更新组件自q状态,所以EDA架构Q每个组仉不会(x)依赖其他的组Ӟlg之间仅仅通过topic产生兌Q耦合性非怽?br /><br />上面说了两种架构的耦合性,显而易见,耦合性低的架构,扩展性必然好。因为SOA的思\Q当我要加一个新功能Ӟ需要修改原来的代码Q比如原来A服务调用了B,C两个服务Q后来我们想多调用一个服务DQ则需要改A服务的逻辑Q而EDA架构Q我们不需要动现有的代码,原来有B,C两订阅者订阅A产生的消息,现在只需要增加一个新的消息订阅者D卛_?br /><br />从CQRS的角度来_(d)也有一个非常明昄例子Q就是Q端的扩展性。假设我们原来Q端只是用数据库实现的,但是后来pȝ的访问量增大Q数据库的更新太慢或者满不了高q发的查询了Q所以我们希望增加缓存来应对高ƈ发的查询。那对CQRS架构来说很容易,我们只需要增加一个新的事件订阅者,用来更新~存卛_。应该说Q我们可以随时方便的增加Q端的数据存储cd。数据库、缓存、搜索引擎、NoSQL、日志,{等。我们可以根据自q业务场景Q选择合适的Q端数据存储,实现快速查询的目的。这一切都归功于我们C端记录了所有模型变化的事gQ当我们要增加一U新的View存储Ӟ可以Ҏ(gu)q些事g得到View存储的最新状态。这U扩展性在传统架构下是很难做到的?br /><br />可用?br /><br />可用性,无论是传l架构还是CQRS架构Q都可以做到高可用,只要我们做到让我们的pȝ中每个节炚w无单点即可。但是,相比之下Q我觉得CQRS架构在可用性方面,我们可以有更多的回避余地和选择I间?br /><br />传统架构Q因写没有分,所以可用性要把读写合在一L(fng)合考虑Q难度会(x)比较更大。因Zl架构,如果一个系l的高峰期的q发写入很大Q比如ؓ(f)2WQƈ发读取也很大Q比如ؓ(f)10W。那该系l必M化到能同时支持这U高q发的写入和查询Q否则系l就?x)在高峰时挂掉。这个就是基于同步调用思\的系l的~点Q没有一个东西去削峰填谷Q保存瞬间多出来的请求,而必让pȝ不管遇到多少hQ都必须能及(qing)时处理完Q否则就?x)造成雪崩效应Q造成pȝ瘫痪。但是一个系l,不会(x)一直处在高峎ͼ高峰可能只有半小时或1时Q但Z保高峰时系l不挂掉Q我们必M用够的gL撑这个高峰。而大部分时候,都不需要这么高的硬件资源,所以会(x)造成资源的浪贏V所以,我们说基于同步调用、SOA思想的系l的实现成本是非常昂늚?br /><br />而在CQRS架构下,因ؓ(f)CQRS架构把读和写分离了,所以可用性相当于被隔d了两个部分去考虑。我们只需要考虑C端如何解军_的可用性,Q端如何解册的可用性即可。C端解军_用性,我觉得是更加Ҏ(gu)的,因ؓ(f)C端是消息驱动的。我们要做Q何数据修Ҏ(gu)Q都?x)发送Command到分布式消息队列Q然后后端消费者处理Command->产生领域事g->持久化事?>发布事g到分布式消息队列->最后事件被Q端消贏V这个链路是消息驱动的。相比传l架构的直接服务Ҏ(gu)调用Q可用性要高很多。因为就我们处理Command的后端消费者暂时挂了,也不?x)?jing)响前端Controller发送CommandQController依然可用。从q个角度来说QCQRS架构在数据修改上可用性要更高。不q你可能?x)说Q要是分布式消息队列挂了呢?呵呵Q对Q这实也是有可能的。但是一般分布式消息队列属于中间Ӟ一般中间g都具有很高的可用性(支持集群和主备切换)Q所以相比我们的应用来说Q可用性要高很多。另外,因ؓ(f)命o(h)是先发送到分布式消息队列,q样p充分利用分布式消息队列的优势Q异步化、拉模式、削峰填谗基于队列的水^扩展。这些特性可以保证即便前端Controller在高峰时瞬间发送大量的Commandq来Q也不会(x)D后端处理Command的应用挂掉,因ؓ(f)我们是根据自q消费能力拉取Command。这点也是CQRS C端在可用性方面的优势Q其实本质也是分布式消息队列带来的优ѝ所以,从这里我们可以体?x)到EDA架构Q事仉动架构)是非常有价值的Q这个架构也体现了我们目前比较流行的Reactive ProgrammingQ响应式~程Q的思想?br /><br />然后Q对于Q端,应该说和传统架构没什么区别,因ؓ(f)都是要处理高q发的查询。这点以前怎么优化的,现在q是怎么优化。但是就像我上面可扩展性里的,CQRS架构可以更方便的提供更多的View存储Q数据库、缓存、搜索引擎、NoSQLQ而且q些存储的更新完全可以ƈ行进行,互相不会(x)拖篏。理想的场景Q我觉得应该是,如果你的应用要实现全文烦(ch)引这U复杂查询,那可以在Q端用搜索引擎,比如ElasticSearchQ如果你的查询场景可以通过keyvalueq种数据l构满Q那我们可以在Q端用Redisq种NoSql分布式缓存。MQ我认ؓ(f)CQRS架构Q我们解x询问题会(x)比传l架构更加容易,因ؓ(f)我们选择更多了。但是你可能?x)说Q我的场景只能用关系型数据库解决Q且查询的ƈ发也是非帔R。那没办法了Q唯一的办法就是分散查询IOQ我们对数据库做分库分表Q以?qing)对数据库做一d备,查询走备机。这点上Q解x\是和传l架构一样了?br /><br />性能、׾~?br /><br />本来x性能和׾~性分开写的Q但是想惌两个其实有一定的兌Q所以决定放在一起写?br /><br />伸羃性的意思是Q当一个系l,?00问时Q性能Q吞吐量、响应时_(d)很不错,?00W问时性能也同样不错,q就是׾~性?00问和100W问,对系l的压力昄是不同的。如果我们的pȝQ在架构上,能够做到通过单的增加机器Q就能提高系l的服务能力Q那我们可以说q种架构的׾~性很强。那我们来想想传l架构和CQRS架构在性能和׾~性上面的表现?br /><br />说到性能Q大家一般会(x)先思考一个系l的性能瓉在哪里。只要我们解决了性能瓉Q那pȝ意味着h通过水^扩展来达到可伸羃的目的了Q当然这里没有考虑数据存储的水qx展)。所以,我们只要分析一下传l架构和CQRS架构的瓶颈点在哪里即可?br /><br />传统架构Q瓶颈通常在底层数据库。然后我们一般的做法是,对于读:(x)通常使用~存可以解军_部分查询问题Q对于写Q办法也有很多,比如分库分表Q或者用NoSQLQ等{。比如阿里大量采用分库分表的Ҏ(gu)Q而且未来应该?x)全部用高大上的OceanBase来替代分库分表的Ҏ(gu)。通过分库分表Q本来一台数据库服务器高峰时可能要承?0W的高q发写,如果我们把数据放到十台数据库服务器上Q那每台机器只需要承?W的写Q相对于要承?0W的写Q现在写1W显得轻村־多了。所以,应该说数据存储对传统架构来说Q也早已不再是瓶颈了?br /><br />传统架构一ơ数据修改的步骤是:(x)1Q从DB取出数据到内存;2Q内存修Ҏ(gu)据;3Q更新数据回DB。d涉及(qing)?ơ数据库IO?br /><br />然后CQRS架构QCQ两端加v来所用的旉肯定比传l架构要多,因ؓ(f)CQRS架构最多有3ơ数据库IOQ?Q持久化命o(h)Q?Q持久化事gQ?Q根据事件更新读库。ؓ(f)什么说最多?因ؓ(f)持久化命令这一步不是必ȝQ有一U场景是不需要持久化命o(h)的。CQRS架构中持久化命o(h)的目的是Z做幂{处理,x们要防止同一个命令被处理两次。那哪一U场景下可以不需要持久化命o(h)呢?是当命令时在创合根Ӟ可以不需要持久化命o(h)Q因为创合根所产生的事件的版本hL?Q所以我们在持久化事件时Ҏ(gu)事g版本号就能检到q种重复?br /><br />所以,我们_(d)你要用CQRS架构Q就必须要接受CQ数据的最l一致性,因ؓ(f)如果你以d的更新完成ؓ(f)操作处理完成的话Q那一ơ业务场景所用的旉很可能比传统架构要多。但是,如果我们以C端的处理为结束的话,则C(j)QRS架构可能要快Q因为C端可能只需要一ơ数据库IO。我觉得q里有一点很重要Q对于CQRS架构Q我们更加关注C端处理完成所用的旉Q而Q端的处理E微慢一Ҏ(gu)关系Q因为Q端只是供我们查看数据用的Q最l一致性)。我们选择CQRS架构Q就必须要接受Q端数据更新有一点点延迟的缺点,否则׃应该使用q种架构。所以,希望大家在根据你的业务场景做架构选型时一定要充分认识到这一炏V?br /><br />另外Q上面再谈到数据一致性时提到Q传l架构会(x)使用事务来保证数据的Z致性;如果事务复杂,那一ơ事务锁的表p多,锁是pȝ伸羃性的大敌Q而CQRS架构Q一个命令只?x)修改一个聚合根Q如果要修改多个聚合根,则通过Saga来实现。从而绕q了复杂事务的问题,通过最l一致性的思\做到了最大的q行和最的q发Q从而整体上提高pȝ的吞吐能力?br /><br />所以,M来说Q性能瓉斚wQ两U架构都能克服。而只要克服了性能瓉Q那伸羃性就不是问题了(当然Q这里我没有考虑数据丢失而带来的pȝ不可用的问题。这个问题是所有架构都无法回避的问题,唯一的解军_法就是数据冗余,q里不做展开了)。两者的瓉都在数据的持久化上,但是传统的架构因为大部分pȝ都是要存储数据到关系型数据库Q所以只能自己采用分库分表的Ҏ(gu)。而CQRS架构Q如果我们只xC端的瓉Q由于C端要保存的东西很单,是命o(h)和事Ӟ如果你信的过一些成熟的NoSQLQ我觉得使用文性数据库如MongoDBq种比较适合存储命o(h)和事ӞQ且你也有够的能力和经验去q维它们Q那可以考虑使用NoSQL来持久化。如果你觉得NoSQL靠不住或者没办法完全掌控Q那可以使用关系型数据库。但q样你也要付出努力,比如需要自p责分库分表来保存命o(h)和事Ӟ因ؓ(f)命o(h)和事件的数据量都是很大的。不q目前一些云服务如阿里云Q已l提供了DRDSq种直接支持分库分表的数据库存储Ҏ(gu)Q极大的化了我们存储命o(h)和事件的成本。就我个言Q我觉得我还是会(x)采用分库分表的方案,原因很简单:(x)保数据可靠落地、成熟、可控,而且支持q种只读数据的落圎ͼ框架内置要支持分库分表也不是什么难事。所以,通过q个Ҏ(gu)我们知道传统架构Q我们必M用分库分表(除非阉Kq种高大上可以用OceanBaseQ;而CQRS架构Q可以带l我们更多选择I间。因为持久化命o(h)和事件是很简单的Q它们都是不可修改的只读数据Q且对kv存储友好Q也可以选择文型NoSQLQC端永q是新增数据Q而没有修Ҏ(gu)删除数据。最后,是关于Q端的瓉Q如果你Q端也是用关pd数据库,那和传统架构一P该怎么优化怎么优化。而CQRS架构允许你用其他的架构来实现QQ所以优化手D늛Ҏ(gu)多?br /><br />l束?br /><br />我觉得不论是传统架构q是CQRS架构Q都是不错的架构。传l架构门槛低Q懂的h也多Q且因ؓ(f)大部分项目都没有什么大的ƈ发写入量和数据量。所以应该说大部分项目,采用传统架构O(jin)K了。但是通过本文的分析,大家也知道了Q传l架构确实也有一些缺点,比如在扩展性、可用性、性能瓉的解x案上Q都比CQRS架构要弱一炏V大家有其他意见Q欢q拍砖,交流才能q步Q呵c(din)所以,如果你的应用场景是高q发写、高q发诅R大数据Q且希望在扩展性、可用性、性能、可伸羃性上表现更优UQ我觉得可以试CQRS架构。但是还有一个问题,CQRS架构的门槛很高,我认为如果没有成熟的框架支持Q很难用。而目前据我了解,业界q没有很多成熟的CQRS框架Qjavaq_有axon framework, jdon frameworkQ?NETq_QENode框架正在朝这个方向努力。所以,我想q也是ؓ(f)什么目前几乎没有用CQRS架构的成熟案例的原因之一。另一个原因是使用CQRS架构Q需要开发者对DDD有一定的了解Q否则也很难实践Q而DDD本n要理解没个几q也很难q用到实际。还有一个原因,CQRS架构的核心是非常依赖于高性能的分布式消息中间Ӟ所以要选型一个高性能的分布式消息中间件也是一个门槛(javaq_有RocketMQQ,.NETq_我个Z门开发了一个分布式消息队列EQueueQ呵c(din)另外,如果没有成熟的CQRS框架的支持,那编码复杂度也会(x)很复杂,比如Event SourcingQ消息重试,消息q等处理Q事件的序处理Qƈ发控Ӟq些问题都不是那么容易搞定的。而如果有框架支持Q由框架来帮我们搞定q些U技术问题,开发h员只需要关注如何徏模,实现领域模型Q如何更新读库,如何实现查询Q那使用CQRS架构才有可能Q因h可能比传l的架构开发更单,且能获得很多CQRS架构所带来的好处?img src ="http://www.aygfsteel.com/paulwong/aggbug/432316.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/paulwong/" target="_blank">paulwong</a> 2017-02-19 08:39 <a href="http://www.aygfsteel.com/paulwong/archive/2017/02/19/432316.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>快速理解聚合根、实体、值对象的区别和联p?/title><link>http://www.aygfsteel.com/paulwong/archive/2017/02/19/432315.html</link><dc:creator>paulwong</dc:creator><author>paulwong</author><pubDate>Sun, 19 Feb 2017 00:32:00 GMT</pubDate><guid>http://www.aygfsteel.com/paulwong/archive/2017/02/19/432315.html</guid><wfw:comment>http://www.aygfsteel.com/paulwong/comments/432315.html</wfw:comment><comments>http://www.aygfsteel.com/paulwong/archive/2017/02/19/432315.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/paulwong/comments/commentRss/432315.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/paulwong/services/trackbacks/432315.html</trackback:ping><description><![CDATA[<img src="http://www.aygfsteel.com/images/blogjava_net/paulwong/13665-20160120152429687-1940741295.png" border="0" alt="" /> <img src ="http://www.aygfsteel.com/paulwong/aggbug/432315.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/paulwong/" target="_blank">paulwong</a> 2017-02-19 08:32 <a href="http://www.aygfsteel.com/paulwong/archive/2017/02/19/432315.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ZSpring Boot, Axon CQRS/ES,和Docker构徏微服?/title><link>http://www.aygfsteel.com/paulwong/archive/2017/02/18/432314.html</link><dc:creator>paulwong</dc:creator><author>paulwong</author><pubDate>Sat, 18 Feb 2017 14:00:00 GMT</pubDate><guid>http://www.aygfsteel.com/paulwong/archive/2017/02/18/432314.html</guid><wfw:comment>http://www.aygfsteel.com/paulwong/comments/432314.html</wfw:comment><comments>http://www.aygfsteel.com/paulwong/archive/2017/02/18/432314.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/paulwong/comments/commentRss/432314.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/paulwong/services/trackbacks/432314.html</trackback:ping><description><![CDATA[q是一个用Spring Boot和Axon以及(qing)Docker构徏的Event Sorucing源码目Q技术特点:(x)<br />1.使用Java 和Spring Boot实现微服?<br />2.使用命o(h)和查询职责分?(CQRS) ?Event Sourcing (ES) 的框架Axon Framework v2, MongoDB ?RabbitMQ;<br />3.使用Docker构徏 交付和运?<br />4.集中配置和用Spring Cloud服务注册;<br />5.使用Swagger ?SpringFox 提供API文<br /><br />目源码Q?a target="_blank">GitHub</a><br /><br />工作原理Q?br />q个应用使用CQRS架构模式构徏Q在CQRS命o(h)如ADD是和查询VIEW(where id=1)分离的,在这个案例中领域部分代码已经分离成两个组Ӟ(x)一个是属于命o(h)q边的微服务和属性查询这边的微服务?br /><br />微服务是单个职责的功能,自己的数据存储,每个能彼此独立扩展部|Ӏ?br /><br />属于命o(h)q边的微服务和属性查询这边的微服务都是用Spring Boot框架开发的Q在命o(h)微服务和查询微服务之间通讯是事仉动,事g是通过RabbitMQ消息在微服务lg之间传递,消息提供了一U进E节Ҏ(gu)微服务之间可扩展的事件蝲体,包括与传l遗留系l或其他pȝ的松耦合通讯都可以通过消息q行?br /><br />h意,服务之间不能彼此׃n数据库,q是很重要,因ؓ(f)微服务应该是高度自治自主的,q样反过来有助于服务能够彼此独立地扩展׾~规模?br /><br />CQRS中命令是“改变状态的动作”。命令的微服务包含所有领域逻辑和业务规则,命o(h)被用于增加新的品或改变它们的状态,q些命o(h)针对某个具体产品的执行会(x)D事gEvent产生Q这?x)通过Axon框架持久化到MongoDB中,然后通过RabbitMQ传播l其他节点进E或微服务?br /><br />在event-sourcing中,事g是状态改变的原始记录Q它们用于系l来重新建立实体的当前状态(通过重新播放q去的事件到当前可以构建当前的状态)Q这听上M(x)很慢Q但是实际上Q事仉很简单,执行非常快,也能采取‘快照’{略q行优化?br /><br />h意,在DDD中,实体是指一个聚合根实体?br /><br />上面是命令这边的微服务,下面看看查询q边的微服务Q?br />查询微服务一般扮演一U事件监听器和视图角Ԍ它监听到命o(h)那边发出的事Ӟ然后处理它们以符合查询这边的要求?br /><br />在这个案例中Q查询这边只是简单徏立和l持了一?‘materialised view’?#8216;projection’ Q其中保留了产品的最新状态,也就是品id和描qC?qing)是否被卖出{等信息Q查询这边能够被复制多次以方便扩展,消息可以保留在RabbitMQ队列中实现持久保存,q种临时保存消息方式可以防止查询q边微服务当机?br /><br />命o(h)微服务和查询微服务两者都有REST APIQ提供外界客L(fng)讉K?br /><br />下面看看如何通过Dockerq行q个案例Q需?Ubuntu 16.04Q?br />1.Docker ( v1.8.2)<br />2.Docker-compose ( v1.7.1)<br /><br />在一个空目录Q执行下面命令下载docker-compose:<br /><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->$ wget https://raw.githubusercontent.com/benwilcock/microservice-sampler/master/docker-compose.yml</div>注意Q不要更Ҏ(gu)件名U?br /><br />启动微服务:(x)只是单一个命令:(x)<br /><br />$ docker-compose up<br /><br />你会(x)看到许多下蝲信息和日志输出在屏幕上,q是Docker image被下蝲和运行。一共有六个dockerQ分别是Q?‘mongodb’, ‘rabbitmq’, ‘config’, ‘discovery’, ‘product-cmd-side’, ?‘product-qry-side’.<br /><br />使用下面命o(h)q行试增加一个新产品Q?br />​<br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->$ curl -X POST -v --header "Content-Type: application/json" --header "Accept: */*" "http://localhost:9000/products/add/1?name=Everything%20Is%20Awesome"</div><br />查询q个C品:(x)<br /><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->$ curl http://localhost:9001/products/1</div><br />Microservices With Spring Boot, Axon CQRS/ES, and Docker <br /><img src ="http://www.aygfsteel.com/paulwong/aggbug/432314.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/paulwong/" target="_blank">paulwong</a> 2017-02-18 22:00 <a href="http://www.aygfsteel.com/paulwong/archive/2017/02/18/432314.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>DDD资源http://www.aygfsteel.com/paulwong/archive/2017/02/18/432313.htmlpaulwongpaulwongSat, 18 Feb 2017 13:53:00 GMThttp://www.aygfsteel.com/paulwong/archive/2017/02/18/432313.htmlhttp://www.aygfsteel.com/paulwong/comments/432313.htmlhttp://www.aygfsteel.com/paulwong/archive/2017/02/18/432313.html#Feedback0http://www.aygfsteel.com/paulwong/comments/commentRss/432313.htmlhttp://www.aygfsteel.com/paulwong/services/trackbacks/432313.html https://github.com/benwilcock/microservice-sampler



https://github.com/AxonFramework/AxonBank

http://www.cnblogs.com/netfocus/p/4150084.html



paulwong 2017-02-18 21:53 发表评论
]]>
վ֩ģ壺 | | ľ| | | | | Զ| | | Ԫ| | | ƽ| ½| | ɳ| | | | | | | | | | Ϫ| ʳ| ̨| ʯɽ| | Ľ| Ӳ| | Ӣɳ| «ɽ| ͤ| | | | |