使用Axon Framework的实际经验

49
作为研究CQRS用于项目的一部分,我遇到了Axon Framework,我想知道是否有人有它的实际使用经验。只是为了清楚,我询问的是框架,而不是作为一个架构设计模式的CQRS。
我的项目已经使用Spring和Spring Integration,这与Axon自己的要求很好地契合,但在我投入大量时间之前,我想知道是否有人有一些第一手的经验。特别是我对文档中不明显的可能存在的问题感兴趣。
6个回答

33
该框架在很大程度上依赖事件溯源,这意味着所有状态更改都会被写入数据存储作为事件。

完全不正确,它并不严重依赖事件溯源。该框架用于存储聚合的实现之一使用了事件溯源,但您也可以轻松地使用提供的类来使用标准关系模型。

但与事件溯源相比,后者更好一些。

因此,您拥有所有数据的历史记录。这很好,但是如果您在生产中更改了域,特别是如果您向客户出售了系统的“强大审计功能”,那么这将是一个非常令人生畏的建议。

我认为使用仅存储当前状态的标准关系模型并不容易得多。

该框架鼓励规范化数据,甚至有些人建议在应用程序中每个视图都使用一个表。这使得您的应用程序极其难以维护,特别是当原始开发人员离开时。

这与框架无关,而与使用的架构模式(CQRS)无关。而且,这里提到只有一个规范化器/视图是一个好主意,因为它保持了一个简单的对象。

因此,维护很容易,因为SQL请求/插入也很容易。所以这个论点不是很有力。怎么样一个视图使用了1000个表模型,在所有地方都有内部连接和复杂的SQL查询?

同样,CQRS有助于解决问题,因为基本上,视图数据只是从对应于该视图的表中选择*。

如果某种方式在其中一个事件处理程序中犯了错误,则您唯一的选择是“重新播放”事件日志,这取决于您的数据大小可能需要很长时间。但是目前没有相关工具。

我同意当前缺乏重放事件的工具,并且可能需要很长时间。但在理论上,只需重放部分事件而不是事件存储的所有内容即可。

重放事件会有副作用,所以开发人员变得不敢使用它。这是不正确的。对我来说,副作用意味着修改系统状态。在事件驱动的CQRS应用程序中,状态存储在事件存储中。重放事件不会修改事件存储。您可以对查询模型产生副作用,但如果出现错误,您仍然可以纠正它并重新播放事件。

如果开发人员没有将域对象的更改存储在事件中,则很容易在使用此框架时出错。下次重放事件时,您将会感到惊讶。

如果您误用或误解了架构、概念等,那么我同意您的观点。但也许问题不在框架本身。

我可以说,对于每个系统,我都会说它与框架本身无关。这就像说,“Java很糟糕,因为如果有人编写了hashCode和equals方法的错误实现,您可以弄乱一切。” 对于您评论的最后部分,我已经看到过使用Spring框架的helloworld示例。当然,在简单示例中完全没有用处。

请注意在评论中区分概念(CQRS + EventSourcing)和框架之间的区别。请区分开来。


6
目前逐渐有一种观点认为CQRS框架“是一坨垃圾”。CQRS不应成为顶层架构,它具有非常特定的用例,这些用例并不像人们想象的那样常见。CQRS是非常特定于任何系统的东西,不能通过创建框架来泛化。Greg Young关于CQRS的观点 - Udi Dahan关于避免使用CQRS的时机 - Simple Fellow

24

由于您表示希望在项目中使用CQRS(我假设JVM是您的目标平台),因此我认为Axon框架是一个非常好的选择。

我曾在其上构建过相当复杂的交易平台(不,交易示例并不复杂),并且没有看到该框架的任何明显缺陷。

由于我使用EventSourcing,测试固定装置使得编写BDD风格的“given,when,then”测试非常容易。这使您可以将聚合视为黑盒子,集中精力检查在输入某个命令时是否产生了正确的事件集。

关于注意事项:在开始之前,请确保:

  1. 您已经理解了CQRS的概念。
  2. 列出所有的聚合、命令处理程序、事件处理程序、saga、命令和事件的清单(纸张、白板等)。这是构建您的系统的难点,需要弄清它应该做什么以及如何做。之后,参考手册应该就能告诉您如何使用Axon把这一切结合在一起。

一些非Axon特定的要点:

从事件中重建视图存储是EventSourcing的一个概念,而不是Axon所特有的。但是我发现创建一个服务来向我发送特定聚合类型、聚合ID或某个事件类型的所有事件非常容易。

能够在项目启动后一年构建一个新的报表组件,并即时获得从项目启动开始的数据报告,这真是太棒了。


你是如何实现事件重放的(正如你所提到的,可以从一开始就获取数据报告)? - sawe
1
有关事件重放,请查看此处:http://www.axonframework.org/docs/2.3/single.html#d5e1824 - Per Wiklander

18
我已经在一个为一家大银行开发的复杂项目中使用AxonFramework超过一年了。需求很高,客户期望也很高,发布时间很紧张。我选择AxonFramework是因为,在项目启动时,它是Java中最完整和最好记录的CQRS实现,设计良好,易于集成、测试和扩展。一年多来,我认为这些考虑因素仍然有效和当前。
另一个考虑因素引导了我的选择:我希望在这样一个困难的项目上的承诺成为我和团队其他成员的培训机会。
我们从AxonFramework 1.0开始开发,并随着新版本的发布而移动到版本1.4。我们对CQRS和AxonFramework提供的实现的团队经验绝对是积极的。它为我们提供了一种一致和统一的方式来开发每个功能,指导我们并使您感到轻松自在。
如果没有它,应用程序的某些功能将更加复杂。我主要是指需要处理的各种长时间运行的进程及其相关的补偿逻辑,还有此处和那里必要的许多业务逻辑片段,这些都适合于CQRS所推广的事件驱动架构中的优雅解耦。
我们的选择是在写模型中保守,因此我们更喜欢基于JPA的持久性而不是事件源。查询模型由视图组成。我们已经尽力确保每个视图都包含单个页面所需的所有必要数据,必要时使用中间视图。
无论如何,我们开发写模型时都像应用事件源一样进行,因此我们只通过事件来修改聚合状态。当客户要求克隆非常复杂的聚合功能时,只需重新播放源事件(带有uuid翻译)到全新实例即可-在这种情况下的缺点是事件向上转换(但这个功能在即将推出的2.0版本中得到了极大的改进)。
与任何项目一样,在开发过程中我们发现了很多错误,主要是在我们的代码中,但也在被认为是成熟和稳定的组件中发现了错误,例如应用程序服务器、IoC容器、缓存、工作流引擎和其他易于在任何大型J2EE应用程序中找到的库。
像任何其他人类产品一样,AxonFramework也不免疫错误,但令人惊讶的是,对于这样一个年轻和利基的项目,错误很少,不重要,并且可以通过新版本快速解决。
作者在邮件列表上提供的友好和及时的支持是另一个宝贵的功能,并在我遇到麻烦时帮助了我很多。
该应用程序已于一年前发布并处于新功能的积极开发和维护状态。客户感到满意并要求更多。

什么时候使用AxonFramework更多的是关于何时使用CQRS。为了回答这个问题,值得回到官方文档:http://www.axonframework.org/docs/1.4/introduction.html#d4e51

在我们的情况下,肯定是值得的。


10

这个问题的重点在于与Axon Framework相关的陷阱,而不是CQRS。这使得这个问题很难回答,因为Axon最初是一个相当忠实地实现了Eric Evans著名书籍的框架。

主要优势在于它确切地做到了它所说的:为您处理基于CQRS设计的难点:聚合、saga、事件源、命令处理程序、事件处理程序、BASE一致性等。当您遵循最佳实践时,您将获得高度响应和水平可扩展的应用程序。如果您将其与事件源配合使用,则您的数据完全可审计,并且至少在理论上,您可以确定应用程序在任何给定时间点的状态。没有提供此工具;您将不得不自己开发。

该框架的主要开发者非常亲近且在Java高性能和可伸缩计算方面极为有知识。他倾向于在邮件列表中回答每个问题,通常几小时内就会回复。

这既是优点,也是最大的缺陷:在2014年初,Axon Framework严重依赖于一个人。

我想提到的其他缺点可能更多是事件溯源而不是CQRS或Axon本身导致的。(截至2018年,该框架由Axoniq公司支持)

在设计您的数据模型时,请仔细考虑。虽然添加数据很容易,但对数据模型进行基本更改可能非常困难。如果在数据模型中犯了基本错误,则应用程序可能无法正常运行或表现不佳。例如,如果选择树形数据模型,在顶部有一个长时间存活的聚合根,则该聚合根可能会随着时间的推移累积越来越多的事件而变得非常庞大,并且它可能需要很长时间才能加载和存储。如果这种情况一直持续到某个聚合的实例无法适应RAM,则不知道会发生什么,但我想会很糟糕。不要这样做。

另一个陷阱(与事件溯源相关)是,经过多次修订后,聚合状态的推理可能变得越来越困难,因为你有时不仅需要记住代码今天的操作,还要记住它在过去的操作。这绝对使得重放(部分)事件存储以重建视图表成为一项非常棘手的任务。
修复数据错误可能比“传统”设计更加困难。你通常需要创建一个命令来更改应用程序的状态,而不是使用简单的SQL语句。如果数据中的错误是由于错误的事件处理程序导致的,你通常只需修复错误,清除快照并重新播放聚合的事件即可。如果你的错误导致应用了虚假事件,那么修复起来可能会更加麻烦。错误的事件将保留在事件存储中,你可能需要应用一些新的事件来恢复数据到正确的状态,或者更改代码以忽略或修复它们的行为。

7

尽管该框架本身写得还不错,但在实际项目中使用却是一场噩梦,我认为选择这个框架是导致该项目失败的重要因素之一。

该框架严重依赖事件溯源,这意味着所有状态更改都会被写入数据存储作为事件。因此,您拥有所有数据的历史参考。这很好,但如果您已经在生产中销售了系统的“强大审计功能”,那么在更改域时将变得非常困难。

您不能让运维人员对数据库进行即兴更改

该框架鼓励对数据进行去规范化处理,甚至有人建议在应用程序中每个视图都有一个表。这使得您的应用程序非常难以维护,特别是当原始开发人员离开后。

如果您在其中一个事件处理程序中犯了错误,则唯一的选择是“重放”事件日志,这取决于您的数据大小可能需要很长时间。但是,这方面的工具不存在。重放可能会产生副作用,因此开发人员会害怕这样做。

使用这个框架时,开发者很容易出错。如果他们不将对域对象的更改存储在事件中,下次重放事件时就会出现意外情况。应该存储增量还是绝对值?如果你不监控开发者,最终你会同时遇到这两种情况,而且你会很惨。

实际上,这个框架几乎没有被采用,因此搜索答案并没有什么用处。

尽管该框架目前不支持分布式,但它是为此编写的,由于此原因,API 非常难以使用。默认情况下,触发事件是异步的,如果您想检查执行命令时是否引发了异常(例如,重复的用户名异常),则需要向命令处理程序传递一个侦听器,该侦听器是一个 future,然后等待 future 的结果返回,处理任何已检查的异常、InterruptedException 等,然后才能从 future 中获取抛出的异常。当然,从 API 中无法明确哪些异常可能会被命令引发,这违背了已检查异常的目的。

查看一些示例应用程序。我需要一个工作单元监听器来创建一个通讯录应用程序?天哪...


谢谢您的回答。您在项目中使用的Axon版本是哪个? - mhvelplund
我尊重地不同意@PerWiklander的观点,因为我认为他对问题的解释过于狭隘。我认为OP想要的是真实的经验,而MartinFlower提供了这种经验。即使他可能没有抓住重点,但MartinFlower的经验为我们所有人提供了一些指导。 - Sarge
7
他的名字是马丁·弗劳尔,不是福勒。 - Songo
1
听起来你并不需要使用CQRS/ES应用程序,但是你却使用了并且后悔了。 - user299709
1
哦,拜托,对缺点的诚实看法和所有的踩?非常成熟的各位。我们需要这里的所有优缺点。 - Bertie

6

我目前与一个团队一起工作,开发一个在线赌场平台,我们将在今年夏天推出我们的品牌Casumo。该域名和平台是使用Axon Framework构建的,到目前为止,它已经为我们提供了可靠的服务。

没有必要构建所有需要的基础设施,如命令处理、事件路由、事件源等等,这样就节省了很多时间,而且API非常易于使用。到目前为止,我们在框架中发现的唯一一个错误在12小时后的发布中得到了修复,Allard总是很快地接受新功能的建议,并讨论如何利用框架来满足您的需求。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接