18

领域驱动设计框架Axon实践

 3 years ago
source link: http://dockone.io/article/10711
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

背景

2004年,Eric Evans发表了Domain Driven Design(领域驱动设计,DDD)这一著作,并在书中对领域驱动作出了开创性的理论阐述,至今领域驱动设计已问世十几年。

近几年来随着微服务盛行, ES(Event Sourcing)事件溯源和CQRS(Command Query Responsibility Segregation)读写分离也成为了一个越来越流行的概念,使用ES和CQRS好处在此不做赘述,但是也存在颇多弊端,比如事件数量巨大、回溯状态需要提前预热、缺少成熟的框架支撑等。在这种情况下,2009年Allard Buijze在JVM平台开源了Axon Framework用来解决此问题,简单说来Axon就是集成了DDD、ES和CQRS于一身,落地实现的一套框架方案,并成立了一家公司Axon IQ,专门与Axon产品合作。

爱奇艺号技术团队,在实施微服务化过程中,应用领取驱动思想,采用Axon框架落地了多个服务,下面是实施过程中的经验总结。

技术选型

爱奇艺号合同中台面向用户提供签约功能,从发起签约到运营审核、供应商、采购单、扫描件、归档等流程漫长,状态颇多,业务较为复杂,同第三方系统交互较多,对于有问题数据需要进行定位和回溯。项目初期为了更好的满足这些需求,我们调研了一下比较成熟的框架,包括Cola、Axon、Activiti、Spring StateMachine等,图1是框架的一些对比:

EBnArej.png!mobile

图1

从对比中可以看出,Axon支持事件回溯,排查历史问题较为方便,并且官方文档完善,一直处于更新维护中。StateMachine较为轻量,流程变更对于历史数据兼容性良好。综合考虑采用Axon+StateMachine相结合,实现简版工作流引擎。

Axon框架介绍

Axon框架的程序遵循基于领域驱动设计(DDD)、命令查询责任隔离 (CQRS)、事件驱动架构(Event Driven Architecture,EDA)的体系结构模式,这些原则的结合,使基于Axon的程序更加健壮、适应性更强。图2是基于Axon框架程序的典型体系结构:

fERFVbe.png!mobile

图2

基于Axon框架程序的典型体系结构图特性如下:

  • 领域驱动模型:可以使业务实体不会“贫血”,更加饱满,实现高内聚、低耦合;
  • 命令查询责任隔离:命令模型和查询模型的分离,使得每个模型更容易理解,更易开发维护,天然适合高并发场景;
  • 事件驱动架构:支持事件溯源,方便对历史事件重放,记录数据变化完整过程,便于BI分析、线上问题排查、还原系统状态到任意时间点等。

Axon系统调用链如图3所示:

eQNryu6.gif!mobile

图3

Spring StateMachine介绍

Spring StateMachine是使用 Spring框架下的状态机概念创建的一种应用程序开发框架。它使得状态机结构层次化,简化了配置状态机的过程。拥有有现状态机的特性功能:现态、条件、动作、次态,支持触发器、状态转移器、保护机制、状态转移动作和状态事件监听器,可基于ZooKeeper实现分布式状态机,可配置多层次、结构复杂的状态机。图4是简单配置效果图:

aUbmymY.jpg!mobile

图4

爱奇艺号合同中台服务实践

项目介绍

用户入驻爱奇艺号后发表作品会获得分成收益,账号满足一定条件后可以申请提现,提现之前需要跟公司签约电子合同。为了保证合同安全有效,线上签约流程比较漫长,包括用户填写信息、运营审核、采购单申请审核、合同审核、合同附件盖章邮寄、作品关联等等,累计20+状态,业务逻辑较为复杂,需求迭代变更频繁,对数据一致性要求较高。

项目1.0版本采用的是Activiti工作流作为引擎设计实现的,基于Activiti特性,可以严格控制每一步状态的流转,历史操作事件都会记录到系统数据库中,对于线上问题排查有一定的优势。但是学习成本较大,需要开发人员了解框架系统的二十多张表功能、使用BMPN进行流程定义设计等。图5是最初版本的流程设计图:

Jnameyv.png!mobile

图5

随着业务的发展,想要修改流程设计,增加一些新状态,此时Activiti的弊端更加暴露出来:如果在原有流程上修改,对于历史数据的显示会报错,如果新增流程,对于正在流程中的数据又没法使用新流程,只能终止掉重新发起。Activiti针对这种流程升级,或者中国特色式的工作流一直没有很好的解决办法,网上的一些解决方法较为复杂,涉及到修改系统内置数据库,实现起来成本较大。针对这种情况,爱奇艺号开发团队对系统进行了升级,采用Axon+Spring StateMachine相结合进行项目架构设计,实现了合同系统2.0版本,最终呈现的结果如图6:

6FBJzuy.jpg!mobile

图6

架构说明如下:

  • 用户接口层:主要是MQ消息、UI和API接口,接收用户请求、运营审批命令、第三方系统交互通知等;
  • 应用层:接口参数校验、组装业务参数,转换成Axon Command进行命令分发;
  • 领域层:接收到领域事件,转换成状态机Event,驱动状态机进行状态更迭,触发对应业务逻辑处理;
  • 基础服务层:提供底层存储服务,第三方服务等。

系统调用流程如下图7:

MV7zIvI.png!mobile

图7

Axon+StateMachine结合,实现简版工作流引擎功能,相比于Activiti更加轻量级。以合同对象多为领域对象,系统操作命令使用状态机进行控制流转。所有对系统的修改操作均以Axon的Command进行,Axon会记录所有对领域对象操作过的事件,可以还原合同生命周期内每一步的状态,对于问题排查,统计分析有着很大的帮助;Snapshot机制对事件进行预热,解决事件过多加载慢的问题;sage对系统失败操作进行补偿事件,保证系统间数据状态的一致性;StateMachine特性,可以修改状态之间流转走向及流转条件,新增状态对于历史数据或者进行中的数据没有影响,对系统的迭代开发有很大的效率提升,天然适合互联网性质工作流。

价值

通过在爱奇艺号后端服务应用Axon框架,可以达成以下效果:

开发方面的优势

  • 转换思维:Java语言开发一直提倡面向对象开发,但是很多业务开发人员的思维还是面向过程开发的思维,按照MVC分层进行业务代码的堆叠。Axon思维更倾向于面向对象,以领域对象为核心,由于领域对象有明确的领域边界,所以容易促进开发人员思维模式的转变。
  • 提升开发效率:项目基于命令模型开发,可以让熟悉业务的开发人员专注于领域层开发,接口和应用层开发则可以由对业务比较陌生的开发人员负责,二者通过命令发送消息机制进行通信。这种职责分离的优势在于不需要所有的开发人员都对业务非常熟悉,减少了熟悉具体业务的时间,且每个开发人员都职责明确,可显著提升开发效率。

运行维护时的优势

  • 便于问题排查:事件溯源机制使得领域对象的每次操作变更状态都有记录,对于排查线上问题有很大的帮助,可以按照先后顺序还原对象的每一步状态。snapshot机制有很好的解决了ES事件预热的问题。对于BI的分析也有着更好的支撑。
  • 支持系统高吞吐量:CQRS的支持,天然适合高并发场景,如果系统有高并发的需求,使用Axon框架可以得到更好的支持。
  • 便于维护和拓展:Axon框架的代码层次清晰,易维护,使用的事件机制让系统更具可扩展性。

难点

  • 分布式事务一致性问题,saga虽然能保证分布式事务的最终一致性,但是实施起来困难很大,需要开发各种补偿机制来实现。而且没有考虑到服务的宕机、幂等、重试支持等问题。
  • 批量事务处理能力较弱,对于一些批量功能,目前只能转换成单独的命令进行处理,没有提供很好的批处理能力。
  • 与Spring Cloud整合问题,Axon支持与Spring Cloud结合,使用分布式消息队列来实现分布式系统间命令的分发,但是目前没有比较良好的实现,中文文档较少,需要进一步研究实施。
  • Axon的充血模型虽然是一大特色,但是实施起来比较繁琐,对于简单的业务实现,贫血模型更加适合。

中文文档少,上手难度较高,国内使用人少,遇到问题可请教或讨论的人少。

未来规划

从4.0版本开始,Axon已经不止是个框架,而是一个由Axon Framework和Axon Server组成的平台。目前官方发布的最新Axon版本已经是v4.3.3,本文中的项目基于Axon框架v3.04进行开发,并且是基于单机事件传播,对于Axon Server机制还未深入研究使用。另外对于一些高级特性如:与Spring Cloud整合、分布式命令、分布式事件、分布式事务等需要进一步实践和总结。Axon命令分发支持与配置AMQP协议的MQ(Message Queue)绑定,MQ用于把Event分发到MQ中,采用这种机制可以针对性的对服务进行更细粒度的拆分,命令分发和处理可以配置成不同的模块,按照各自吞吐量进行服务部署。此外,分布式事务一直是个令人头疼的问题,对于saga的优雅实现需要花费更多的时间进行深入研究。

领域思想的转变对面向对象开发语言有着重大的帮助,成熟的架构支持及持久的维护性对于技术选型有着很大的影响,流行的Axon, Akka, Cola等框架势头正猛,相信领域思想未来会更深入人心。

原文链接: https://mp.weixin.qq.com/s/WF32aNP26ZNhpXY0pDLMDw


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK