作家
登录

在微服务中使用领域事件

作者: 来源: 2017-07-10 14:01:56 阅读 我要评论

复制代码
public class Order {    private List<Event> events;    public Order() {        //create order        //...        events.add(new OrderPlacedEvent());    }    public List<Event> getEvents() {        return events;    }    public void clearEvents() {        events.clear();    }} 
复制代码在测试Order对象时,我们便你可以经由过程验证events集合包管Order对象在创建时切实其实宣布了OrderPlacedEvent事宜:复制代码
@Testpublic void shouldPublishEventWhenCreateOrder() {    Order order = new Order();    List<Event> events = order.getEvents();    assertEquals(1, events.size());    Event event = events.get(0);    assertTrue(event instanceof OrderPlacedEvent);} 
复制代码在这种方法中,聚合根对范畴事宜的保存只能是临时的,在对该聚合根操作完成之后,我们应当将范畴事宜宣布出去并及时清空events集合。可以推敲在持久化聚合根时进行如许的操作,在DDD中即为资本库(Repository):复制代码
public class OrderRepository {    private EventPublisher eventPublisher;    public void save(Order order) {        //save the order        //...        List<Event> events = order.getEvents();        events.forEach(event -> eventPublisher.publish(event));        order.clearEvents();    }}
复制代码除此之外,还有一种与“临时保存范畴事宜”类似的做法是“在聚合根办法中直接返回范畴事宜”,然后在Repository中进行宣布。这种方法依然有很好的可测性,并且开辟人员不消手动清空先前的事宜集合,不过照样得记住在Repository中将事宜宣布出去。别的,这种方法不合适创建聚合根的场景,因为此时的创建过程既要返回聚合根本身,又要返回范畴事宜。 这种方法也有不好的处所,比如它请求开辟人员在每次更新聚合根时都必须记得清空events集合,忘记这么做将为法度榜样带来严重的bug。不过固然如斯,这依然是笔者比较推荐的方法。 营业操作和事宜宣布的原子性 固然在不合聚合根之间我们采取了基于范畴事宜的最终一致性,然则安营业操作和事宜宣布之间我们依然须要采取强一致性,也即这两者的产生应当是原子的,要么全部成功,要么全部掉败,不然最终一致性根本无大年夜谈起。以上文中“订单积分”为例,如不雅客户下单成功,然则事宜发送掉败,下流的┞匪户体系便拿不到事宜,导致最终客户的积分并不增长。 要包管营业操作和事宜宣布之间的原子性,最直接的办法就是采取XA事务,比如Java中的JTA,这种方法因为其重量级并不被人们所看好。然则,对于一些对机能请求不那么高的体系,这种方法未尝不是一个选择。一些开辟框架已经可以或许支撑自力于应用办事器的XA事务治理器(如Atomikos 和Bitronix),比如Spring Boot作为一个微办事框架便供给了对Atomikos和Bitronix的支撑。 如不雅JTA不是你的选项,那么可以推敲采取事宜表的方法。这种方法起首将事宜保存到聚合根地点的数据库中,因为事宜表和聚合根表同属一个数据库,全部过程只须要一个本地事务就能完成。然后,在一个零丁的后台义务中攫取事宜表中未宣布的事宜,再将事宜宣布到消息中心件中。 

图4

这种方法须要留意两个问题,第一个是因为宣布了事宜之后须要将表中的事宜标记成“已宣布”状况,即依然涉及到对数据库的操作,是以宣布事宜和标记“已宣布”之间须要原子性。当然,此时依旧可以采取XA事务,然则这违背了采取事宜表的初志。一种解决办法是将事宜的花费方创建成幂等的,即花费方可以多次花费同一个事宜。这个过程大年夜致为:全部过程中事宜发送和数据库更新采取各自的事务治理,此时有可能产生的情况是事宜发送成功而数据库更新掉败,如许鄙人一次事宜宣布操作中,因为先前宣布过的事宜在数据库中依然是“未宣布”状况,该事宜将被从新宣布到消息体系中,导致事宜反复,但因为事宜的花费方是幂等的,是以事宜反复不会存在问题。 别的一个须要留意的问题是持久化机制的选择。其实对于DDD中的聚合根来说,NoSQL是比拟于关系型数据库更合适的选择,比如用MongoDB的Document保存聚合根就是种很天然的方法。然则多半NoSQL是不支撑ACID的,也就是说不克不及包管聚合更新和事宜宣布之间的原子性。还好,关系型数据库也在向NoSQL偏向成长,比如新版本的PostgreSQL(版本9.4)和MySQL(版本5.7)已经可以或许供给具备NoSQL特点的JSON存储和基于JSON的萌芽。此时,我们可以推敲将聚合根序列化成JSON格局的数据进行保存,大年夜而避免了应用重量级的ORM对象,又可以在多个数据之间包管ACID,何乐而不为? 总结范畴事宜重要用于解耦微办事,此时各个微办事之间将形成最终一致性。事宜风暴晃荡有助于我们对微办事进行拆分,并且有助于我们深刻懂得某个范畴。范畴事宜作为已经产生过的汗青数据,在建模时应当将其创建为弗成变的特别值对象。存在多种方法用于宣布范畴事宜,个中“在聚合中临时保存范畴事宜”的方法是值得推许的。别的,我们须要推敲到聚合更新和事宜宣布之间的原子性,可以推敲应用XA事务或者采取零丁的事宜表。为了避免事宜反复带来的问题,最好的方法是将事宜的花费方创建为幂等的。 

  推荐阅读

  Mysql群集架构mmm高可用群集及服务器上线

【引自攀岩人生的博客】MMM即Multi-Master Replication Manager for MySQL:mysql多主复制治理器,基于perl实现,关于mysql主主复制设备的监控、故障转移和治理的一套可伸缩的脚本套件(在任>>>详细阅读


本文标题:在微服务中使用领域事件

地址:http://www.17bianji.com/lsqh/36107.html

关键词: 探索发现

乐购科技部分新闻及文章转载自互联网,供读者交流和学习,若有涉及作者版权等问题请及时与我们联系,以便更正、删除或按规定办理。感谢所有提供资讯的网站,欢迎各类媒体与乐购科技进行文章共享合作。

网友点评
自媒体专栏

评论

热度

精彩导读
栏目ID=71的表不存在(操作类型=0)