• 阿神
    2019-10-25
    微服务内的领域事件我建议少用,增加复杂性了

    作者回复: 我跟你的观点一样。

     6
     14
  • 杨杰
    2019-10-28
    关于领域事件有几个问题:
    1、如果采用了主流的消息队列(如rabbitmq,kafka,rocketmq),是否领域事件还需要持久化?
    2、对于领域事件的内容,是否需要把所有变化(或绝大多数)的内容都保存到事件里面(比如保单里面的所有内容)?这样的话这个这个领域事件会不会比较大?
    3、关于领域事件还有一种方案就是基于数据库cdc的方式,在系统中有大量领域事件的场景下,是否cdc的形式更加灵活一点?

    作者回复: 第一个问题:虽然这些消息队列自身有持久化的功能,但是中间过程,或者在订阅到数据后,在处理之前出问题,需要进行数据对账,这样就没法找到发布时和处理后的数据版本。关键的业务数据我建议还是落库比较好。
    第二个问题:事件实体的业务数据还是按需发布比较好,避免不必要的业务信息泄露。
    第三个问题:CDC的设计方式比较简单,属于数据库底层的技术,不会对上层应用产生太多的影响。

     2
     4
  • zj
    2019-11-21
    spring提供的事件机制我感觉也可以啊,可以用在微服务内

    作者回复: 现在的技术路线很多,只要能保证在一个事务在修改多个聚合数据时,能保证数据一致性就可以使用。

    
     2
  • Geek_a91670
    2019-10-31
    "微服务内应用服务,可以通过跨聚合的服务编排和组合,以服务调用的方式完成跨聚合的访问,这种方式通常应用于实时性和数据一致性要求高的场景。这个过程会用到分布式事务,以保证发布方和订阅方的数据同时更新成功。"
    -------服务类的领域事件怎么还牵扯到分布式事务了呢?

    作者回复: 如果一个领域事件会同时修改多个聚合之间的数据的话,可能会存在不同聚合内数据一致性的问题。事件总线的方式可以以同步或者异步的方式来保证聚合之间数据的一致性。多个聚合之上的应用服务也可以来协调这种数据一致性,但由于是跨聚合,需要保证多个聚合同时成功,这可以用事务的方式来实现。但是由于在同一个微服务内的进程内,出错的概率要比微服务之间小得多。

     2
     2
  • 朱振光
    2019-10-25
    内容很充实,但还是有两个问题。
    1. 在采取最终一致性的情况下,event消费端如果出现错误,消费失败,但是之前的业务都成功了,虽然记录了event dB,但是后续如何处理,是需要人工介入解决吗?如果人工介入再解决,前端用户会不会看到数据不一致,体验不好?
    2. 因为event都是异步发送,当最后一个event消费成功后,如何有效的通知前端界面,是用Web Socket吗?还是需要前端轮询到后台看是否都成功

    作者回复: 第一个问题,失败的情况应该比例是很少的。失败的信息可以采用多次重发的方式,如果这个还解决不了,只能将有问题的数据放到一个问题数据区,人工解决。当然要确保一个前提,要保证数据的时序性,不能覆盖已经产生的数据。
    第二个问题,一般来说发布方不会等待订阅方反馈结果。发布方有发布的事件表,订阅方有消费事件表,你可以采用每日对账的方式来发现问题数据。

    
     2
  • Luke
    2020-02-01
    将事件发布放在应用层是否合适呢,还是应该视具体业务来? 看到老师的「领域事件运行机制相关案例」中,「创建缴费通知单事件」是在应用层,独立发布的。我们开发的业务中,事件发布的调用直接放在领域层逻辑中了。

    作者回复: 事件发布应用层和领域层两个都是可以的,看具体情况。事件接收建议放应用层。

     1
     1
  • 兆哲
    2020-01-31
    在公司与同事沟通微服务之间的关系的时候,DDD提倡服务之间使用领域事件进行解耦,
    但是某些同事觉得,rpc调用与通过总线发布事件,在执行的内容上没有本质上减少的东西(RPC
    调用失败也可以加入重试机制),并且这种解耦方式可能会导致追踪调用链路更加困难。
    如何看待这样的解读呢?

    作者回复: 在微服务设计时,微服务之间尽量通过领域事件的方式来解耦,耦合度过高,在一个微服务出现问题时容易导致整体出现雪崩现象。这种异步方式不仅可以解耦微服务,还可以起到削峰填谷的作用。所以非实时的调用尽量采用领域事件的方式。

    
     1
  • 达文西
    2019-12-19
    不明白为什么同一个微服务内不同的聚合之间需要使用分布式事务,不是用本地事务就可以 了吗?还是说这里不同的聚合已经是使用不同的数据库了?
     2
     1
  • 堵车
    2019-12-16
    我看到第一条留言,微服务领域时间建议少用,增加了复杂性。我有这么一个场景,用户入住一个房间后,要修改房态。如果不用领域事件,那么就得将入住和改房态写在同一个事务里。这里面入住是主操作,改房态是副操作。副操所除了问题,导致事务回滚,主操作也将无效,用户入住不成功。

    作者回复: 在微服务内,不是少用领域事件,是少用事件总线。在DDD中是以聚合为单位进行数据管理的,如果一次操作会修改同一个微服务内的多个聚合的数据,你就需要保证多个聚合的数据一致性,为了解耦不同聚合,你需要采用分布式事务或者用事件总线两种方式,用事件总线不太方便管理服务和数据的关系,你可以用类似saga之类的分布式事务技术。总之需要确保你的不同聚合的业务规则和数据一致性,尽量减少系统建设复杂度。

     1
     1
  • itrickzhang
    2019-12-11
    欧老师我想问下,微服务之间用消息中间件通讯,那么注册中心是否是微服务设计的一个鸡肋

    作者回复: 不是这样的。消息中间件主要用于微服务之间的异步处理,其实很多场景还是实时服务调用的。

     2
     1
  • 观弈道人
    2019-10-28
    欧老师你好:事件有没有被消费成功(消费端成功拿到消息或消费端业务处理成功),一般如何通知到消息生产端?谢谢。

    作者回复: 因为事件发布方有事件实体的原始的持久化数据,事件订阅方也有自己接收的持久化数据。一般可以通过定期对账的方式检查数据的一致性。

     2
     1
  • 游泳速度快内裤跟不上
    2019-10-25
    跨微服务的聚合间的领域事件驱动用消息中间件来衔接,这个比较容易理解,同一微服务内的聚合间的在实现层面如何来衔接呢,不太清楚这里面说的事件总线是一个什么概念,这个落实到代码上的话具体如何实现呢

    作者回复: 事件总线你可以理解为运行在同一个进程内的消息中间件,它是一个很小的技术组件,可以通过配置支持异步或同步的消息机制。具体实现你可以查阅一下Eventbus组件相关的资料。

    
     1
  • Jie
    2020-02-02
    感觉通过领域事件解耦后,需要更多考虑发布方的重试机制,和订阅方的调用幂等。

    作者回复: 是的,跟消息队列的使用基本类似。

    
    
  • maomaostyle
    2020-01-21
    请问老师,过多的服务间消息传递是否会带来延迟等性能问题?也就是对消息中间件的依赖太大了,另外对性能要求高的业务还是应优先使用rpc的方式直接访问吧?

    作者回复: 消息中间件就是最终一致性,肯定会有延迟,但是现在消息中间件的处理能力非常强,延迟应该不会太大。实时的你可以分布式事务方式。

    
    
  • alex
    2020-01-19
    欧老师,您好,这个领域事年章节,我反复看了多次,基本上能领会你这里用事件驱动+消息中间件形式解耦多个微服务之间的调用,但为了实现两个微服务之间调用时的事务一致性的问题 ,要考虑到A调用B,但B服务在执行时出现异常而终止,这时应该有机制使B服务的方法重试执行,确保事务或数据的最终一致,请问处理这种过程的,有没有现成的中间件框架可以直接使用,能实现事件信息落库,发布异步消息通知,服务执行时,能监控到并使之重试实现数据的最终一致。

    作者回复: 分布式事务有saga之类的组件。
    异步方式在出现异常时需要根据自己的场景采用不同的策略,如多次重传或者转人工处理等。

     1
    
  • C J J
    2020-01-15
    老师,领域事件是否可理解成MySQL的binlog?

    作者回复: 在这一节的设计中,我只是将领域事件的数据放到了数据库的事件表中,然后通过CDC之类工具将领域事件的增量逻辑日志提取并发布到消息队列中。采用基于数据库日志的原因主要是剥离业务逻辑与领域事件数据传输逻辑。
    领域事件和Binlog不是一个维度的东西。

     1
    
  • cup
    2020-01-06
    老师,您好,有几个问题想请教一下
    1、领域事件和一般的微服务之间的rpc调用区别是什么,因为大部分通信还是同步的rpc或者http调用,那每次rpc调用做一次更新操作就是一次领域事件么

    2、大家都比较疑惑的问题
    “微服务内应用服务,可以通过跨聚合的服务编排和组合,以服务调用的方式完成跨聚合的访问,这种方式通常应用于实时性和数据一致性要求高的场景。这个过程会用到分布式事务,以保证发布方和订阅方的数据同时更新成功。”
    老师的答案是:微服务内主要是因为跨聚合了。一个聚合一个仓储,在一次修改多个聚合的时候,可能会存在数据不一致的情况,所以用事件总线或者分布式事务。

    您这里说的一个聚合一个仓储是指的不同的聚合使用不同的数据库是么?普通数据库事务无法保证跨库操作的数据一致性,所以使用分布式事务?这样做是为了不同聚合之间解耦,方便以后的微服务拆分?
    但如果简化一下,可不可以同一微服务中不同聚合的数据放在一个库里,在应用服务开启数据库事务,操作两个聚合的数据,然后结束事务

    3、同一个微服务内为什么不能用消息中间件呢,比如一个聚合生产,扔到rabbitmq,同一微服务里面另一个聚合消费
    消息保存到进程内部,如果消费能力较低,会不会内存溢出
    展开

    作者回复: 1、领域事件方式主要是采用异步方式,实现数据的最终一致性。
    2、一个聚合一个仓储,是指一个聚合与数据库交互的仓储服务是一个,并不是指一个聚合一个数据库。因为在DDD中为了保证聚合内数据和业务规则的一致性,通过聚合根将所有的实体等数据作为一个整体持久化到数据库中,所以一次事务只能修改一个聚合的数据。而如果一个操作跨了多个聚合的话,就需要考虑事务的概念了,其中有两种实现方式:最终一致性的事件总线机制和Saga等分布式事务的方式。这样也是为了聚合之间的解耦。
    3、在同一个微服务内采用消息中间件过重了,事件总线属于轻量级的可实现发布订阅基本功能。

    
    
  • shitao
    2019-12-28
    绩效文档打分完成就是领域事件,会触发后续的审批流程,通知流程等

    作者回复: 是的

    
    
  • james.d
    2019-12-20
    微服务内应用服务,可以通过跨聚合的服务编排和组合,以服务调用的方式完成跨聚合的访问,这种方式通常应用于实时性和数据一致性要求高的场景。这个过程会用到分布式事务,以保证发布方和订阅方的数据同时更新成功。
    这个观点貌似大家的疑惑都比较多, 可以在领域服务内实现跨聚合的调用,然后由领域服务来保证事务,这样可以避免引入分布式事务。当然这也只是一种折中,因为DDD中最好是基于聚合的维度来保证强一致,跨聚合的应该保证最终一致性。

    作者回复: 领域服务之间调用容易导致聚合之间耦合度过高,不利于微服务的架构演进,因此建议通过应用服务来编排。

    
    
  • 达文西
    2019-12-19
    不要在同一个事务中修改不同聚合的数据,是为了方便后续微服务拆分解耦吗?那如果很清楚不同的聚合日后不会分到不同的微服务里面,为了开发的方便,是不是就可以在同一个事务中修改这些聚合的数据了?

    作者回复: 在DDD里面聚合是数据管理的基本单元,都通过聚合的仓储服务来实现持久化,一个聚合有一个仓储,跟传统的一次修改很多不同的数据库表不太一样。两个不同的聚合就是两个不同的数据单元,但在一个事务中,如果一次修改两个聚合数据的话,需保证两个聚合数据的最终一致性。其目的也是为了聚合解耦,方便以后微服务架构的演进。

    
    
我们在线,来聊聊吧