跨微服务数据处理时,对实时性要求高的场景,可选择直接调用应用服务的方式(新增和修改类型操作需关注事务一致性)。对实时性要求不高的场景,可选择异步化的领域事件驱动机制(最终数据一致性)。
数据视图¶DDD 分层架构中数据对象转换的过程如下图。
数据视图应用服务通过数据传输对象(DTO)完成外部数据交换。领域层通过领域对象(DO)作为领域实体和值对象的数据和行为载体。基础层利用持久化对象(PO)完成数据库的交换。 DTO 与 VO 通过 Restful 协议实现 JSON 格式和对象转换。 前端应用与应用层之间 DTO 与 DO 的转换发生在用户接口层。如微服务内应用服务需调用外部微服务的应用服务,则 DTO 的组装和 DTO 与 DO 的转换发生在应用层。 领域层 DO 与 PO 的转换发生在基础层。
领域事件和事件总线¶领域事件是领域模型中非常重要的部分,用来表示领域中发生的事件。一个领域事件将导致进一步的业务操作,有助于形成完整的业务闭环。领域事件主要用于解耦微服务,各个微服务之间不再是强一致性,而是基于事件的最终一致性。
微服务内的领域事件¶微服务内的领域事件可以通过事件总线或利用应用服务实现不同聚合之间的业务协同。当微服务内发生领域事件时,由于大部分事件的集成发生在同一个线程内,不一定需要引入消息中间件。但一个事件如果同时更新多个聚合数据,按照 DDD“一个事务只更新一个聚合根”的原则,可以考虑引入消息中间件,通过异步化的方式,对微服务内不同的聚合根采用不同的事务。
微服务之间的领域事件¶微服务之间的数据交互方式通常有两种:应用服务调用和领域事件驱动机制。 领域事件驱动机制更多的用于不同微服务之间的集成,实现微服务之间的解耦。事件库(表)可以用于微服务之间的数据对账,在应用、网络等出现问题后,可以实现源和目的端的数据比对,在数据暂时不一致的情况下仍可根据这些数据完成后续业务处理流程,保证微服务之间数据的最终一致性。 应用服务调用方式通常应用于实时性要求高的业务场景,但一旦涉及到跨微服务的数据修改,将会增加分布式事务控制成本,影响系统性能,微服务之间的耦合度也会变高。
事件总线¶事件总线位于基础层,为应用层和领域层服务提供事件消息接收和分发等服务。其大致流程如下: 1、服务触发并发布事件。 2、事件总线事件分发。
如果是微服务内的订阅者(微服务内的其它聚合),则直接分发到指定订阅者。
如果是微服务外的订阅者,则事件消息先保存到事件库(表)并异步发送到消息中间件。
如果同时存在微服务内和外订阅者,则分发到内部订阅者,并将事件消息保存到事件库(表)并异步发送到消息中间件。为了保证事务的一致性,事件表可以共享业务数据库。也可以采用多个微服务共享事件库的方式。当业务操作和事件发布操作跨数据库时,须保证业务操作和事件发布操作数据的强一致性。
事件数据持久化¶事件数据的持久化存储可以有两种方案,在项目实施过程中根据具体场景选择最佳方案。
事件数据保存到微服务所在业务数据库的事件表中,利用本地事务保证业务操作和事件发布操作的强一致性。
事件数据保存到多个微服务共享的事件库中。需要注意的一点是:这时业务操作和事件发布操作会跨数据库操作,须保证事务的强一致性(如分布式事务机制)。
事件数据的持久化可以保证数据的完整性,基于这些数据可以完成跨微服务数据的一致性比对。
微服务设计方法¶ 事件风暴¶本阶段主要完成领域模型设计。 基于 DDD 的微服务设计通常采用事件风暴方法。通过事件风暴完成领域模型设计,划分出微服务逻辑边界和物理边界,定义领域模型中的领域对象,指导微服务设计和开发。事件风暴通常包括产品愿景、场景分析、领域建模、微服务设计和拆分等过程。本文不对事件风暴详细方法做深入描述,如感兴趣可查阅相关资料。
1、产品愿景