/enode

DDD 框架

Primary LanguageKotlinMIT LicenseMIT

框架简介

enode是基于JVM平台,为业务实践Domain Driven Design**而落地的一个应用框架,使用CQRS, Event Sourcing设计模式,让开发者可以专注于业务模型建模和业务逻辑开发

框架特色

  • Reactive
    • enode是完全响应式的框架,是实现高吞吐的核心设计
    • db层面使用了异步驱动,实现全链路异步
    • 针对IO密集型操作,集成了kotlin coroutine
  • Event Sourcing
    • 聚合根的事件完全持久化,记录聚合根的状态变化,让C端的数据可追溯,数据持久化变得通用化
  • Event Driven
    • 业务流程以事件驱动为核心,让研发更聚焦业务中领域事件的建设和积累
    • 先进的Saga机制,以事件驱动的流程管理器(Process Manager)的方式支持一个用户操作跨多个聚合根的业务场景,如订单处理,从而避免分布式事务的使用
  • CQRS
    • 基于CQRS架构**,enode解决了CQRS架构的C端的高并发写的问题,以及CQ两端数据同步的顺序性保证和幂等性
    • 支持Fire And ForgetFire And Wait两种方式返回命令执行结果
  • Fast and Flexible
    • 聚合根常驻内存(In-Memory Domain Model),在设计上尽可能的避免了聚合根重建,可以完全以OO的方式来设计实现聚合根,不必为ORM的阻抗失衡而烦恼
    • 聚合根的处理基于Actor**,乐观并发控制,无锁,在事件持久化层面使用Group Commit Domain Event提高写性能

enode在架构层面严格规范了研发人员该如何写代码,要求用DDD的方式思考,严格遵守聚合内强一致性、聚合之间最终一致性的原则

在设计上遵循SOLID,以下均可扩展替换成自建

  • 针对IoC容器,目前SpringBoot友好适配
  • 针对CommandBus,只要求最基础的队列能力,目前适配了KafkaRocketMQPulsarAMQP
  • 针对EventStore,适配了MySQLPostgreSQLMongoDB
  • 针对ReplyService,要求实现点对点通信模型,实现Command处理结果的通知

使用约束

  • 一个命令一次只能修改一个聚合根
  • 聚合间只能通过领域消息交互
  • 聚合内强一致性
  • 聚合间最终一致性

发版记录

CHANGELOG

整体架构

Saga的两种模式

  • 编排(Choreography) 参与者(子事务)之间的调用、分配、决策和排序,通过交换事件进行进行。是一种去中心化的模式,参与者之间通过消息机制进行沟通,通过监听器的方式监听其他参与者发出的消息,从而执行后续的逻辑处理。

enode中使用的就是这种模式

  • 控制(Orchestration) 提供一个控制类,方便参与者之间的协调工作。事务执行的命令从控制类发起,按照逻辑顺序请求Saga 的参与者,从参与者那里接受到反馈以后,控制类在发起向其他参与者的调用。所有Saga的参与者都围绕这个控制类进行沟通和协调工作。

Apache ServiceComb 使用的是这种模式

编程模型

新增了三个注解,系统限定了只扫描@Command@Event标识的类,执行的方法上需要添加@Subscribe注解:

  • @Command
  • @Event
  • @Subscribe

启动时会扫描包路径下的注解,注册成Spring Bean,和@Component作用相同。

基础组件依赖

docker部署

定义了docker-compose.yml,搭配docker-compose快速的在启动一套运行环境,用于应用的测试

docker-compose up -d

消息

  • 目前enode函数调用的实现是放在kotlin coroutine中来执行的,这里涉及到实际执行的任务类型,针对计算密集型和IO密集型的任务,目前没有做可定制化的配置,后续的版本会考虑加上, 使用也很简单,@Subscribe 方法体加上suspend标记即可

  • 针对Java异步编程做了深度优化,支持CommandHandlerEventHandler中定义CompletableFuture 返回值,阻塞调用封装在协程中,避免使用#join() #get()等阻塞代码,同时也支持kotlin suspend

详细介绍

最佳实践

可参考samples模块中的例子

转账的例子中,转账的业务场景,涉及了三个聚合根:

  • 银行存款交易记录,表示一笔银行存款交易
  • 银行转账交易记录,表示一笔银行内账户之间的转账交易
  • 银行账户聚合根,封装银行账户余额变动的数据一致性

command-web启动

  • CQRS架构中的Command端应用

主要用来接收来自用户的Command请求,核心是将Command发送到消息队列。

command-consumer启动

  • 消费Command队列中的消息的服务

将领域事件消息持久化才算是Command执行成功,Command执行的结果可以通过发送命令时注册的监听器获取。

event-consumer启动

  • 领域事件处理服务

事件可能会多次投递,所以需要消费端逻辑保证幂等处理,这里框架无法完成支持,需要开发者自己实现。

See Also

conference

参考项目