作为研究用于项目的 CQRS 的一部分,我遇到了Axon 框架,我想知道是否有人对它有任何真实的生活经验。为了清楚起见,我问的是框架,而不是 CQRS 作为架构模式。
我的项目已经使用了 Spring 和 Spring Integration,它非常符合 Axon 自己的要求,但是在我投入大量时间之前,我想知道是否有人有一些第一手经验。特别是我对文档中没有立即明显的可能陷阱感兴趣。
该框架严重依赖事件源,这意味着所有状态更改都作为事件写入数据存储。"
这是完全不真实的,它并不严重依赖事件溯源。在此框架中存储聚合的实现之一使用事件溯源,但您也可以轻松地使用提供的类来使用标准关系模型。
事件溯源会更好。
因此,您拥有所有数据的历史参考。这很好,但是在您投入生产之后更改您的 > 域是一个非常令人生畏的提议,特别是如果您以系统的“强大的可审计性”出售 > 客户“
我认为使用仅存储当前状态的标准关系模型并不容易。
该框架鼓励对您的数据进行非规范化,以至于有些人建议在应用程序中为每个视图创建一个表。这使您的应用程序极其 > 难以维护,尤其是当原始开发人员离开时”
这与框架无关,但与使用中的架构模式(CQRS)有关。遗憾的是,拥有一个非规范化器/视图是一个好主意,因为它仍然是一个简单的对象。
所以维护很容易,因为 SQL 请求/插入也很容易。所以这个论点不是很强。一个使用 1000 个表模型的视图怎么样?到处都有内部连接和复杂的 SQL 查询?
同样,CQRS 也有帮助,因为基本上,视图数据只是表中对应于视图的 SELECT *。
如果不知何故您在其中一个事件处理程序中犯了错误,您唯一的选择是>“重播”事件日志,这取决于您的数据大小可能需要很长时间。然而,用于此的工具是不存在的。
我同意目前缺乏重播事件的工具并且这可能需要很长时间的观点。但是,理论上可以只重放事件的一部分,而不是事件存储的所有内容。
重放可能会产生副作用,因此 > 开发人员害怕这样做
重播事件有副作用 -> 这是不正确的。对我来说,副作用意味着修改系统的状态。在事件源 CQRS 应用程序中,状态存储在事件存储中。重放事件不会修改事件存储。您可以对模型的查询端产生副作用是的。但是您不在乎是否犯了错误,因为您仍然可以纠正错误并再次重播该事件。
开发人员很容易搞砸使用这个框架。如果他们没有在事件中存储对域对象的更改,那么下次您重播事件时,您会感到惊讶。
好吧,如果您误用和误解了架构、概念等,那么我同意您的看法。但也许问题不在于这里的框架。
你应该存储三角洲的吗?绝对值?如果您不密切关注您的开发人员>您一定会同时拥有这两者,您将被f***ed
我可以说,对于每个系统,我都会说它与框架本身没有直接关系。这就像说,“Java 是垃圾,因为如果有人编写了错误的 hashCode 和 equals 方法实现,你可能会搞砸一切。”
对于您评论的最后一部分,我已经看到了带有 Spring 框架的 helloWorld 之类的示例。当然,在一个简单的例子中它是完全没用的。
请注意您的评论,以便在概念(CQRS + EventSourcing)和框架之间有所不同。请有所作为。
既然您已经声明要在您的项目中使用 CQRS(并且我假设 JVM 是您的目标平台),我认为 Axon Framework 是一个很好的选择。
我已经在上面建立了一个相当复杂的交易平台(不,交易样本并不复杂),我没有看到框架有任何明显的缺陷。
由于我使用 EventSourcing,测试装置使得编写 BDD 风格的“给定、何时、然后”测试变得非常容易。这使您可以将聚合视为黑匣子,并专注于检查在您输入某个命令时是否出现了正确的事件集。
关于陷阱:在跳入之前,请确保
一些非轴突特定点:
能够从事件重建视图存储是 EventSourcing 的一个概念,而不是 Axon 独有的东西,但我发现创建一个服务非常容易,该服务将向我发送来自聚合类型、聚合 id 或某个特定的所有事件事件类型。
能够在项目启动一年后构建新的报告组件,并立即获得项目启动时及以后的数据报告,这真是太棒了。
在为一家大银行开发的复杂项目中,我已经使用 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
在我们的案例中,这绝对是值得的。
OP 特别询问与 Axon 框架而不是 CQRS 相关的陷阱。这使得这个问题很难回答,因为 Axon 最初是对埃里克·埃文斯 ( Eric Evans ) 著名著作的相当忠实的实现
主要优点是它完全按照它所说的那样做:它为您处理基于 CQRS 的设计的困难部分:聚合、sagas、事件源、命令处理程序、事件处理程序、BASE 一致性等。当你遵循最好的实践,你最终得到一个高度响应和水平可扩展的应用程序。如果您将它与事件溯源一起使用,您的数据是完全可审计的,并且至少在理论上,您可以确定您的应用程序在任何给定时间点的状态。没有提供执行此操作的工具;你将不得不自己动手。
该框架的主要开发人员非常平易近人,并且对 java 中的高性能和可扩展计算主题非常了解。他倾向于在几个小时内回答邮件列表上的每个问题。这既是优势也是主要缺陷:此时(2014 年初),Axon 框架严重依赖于一个人。我想提到的其余陷阱可能更多是事件溯源的结果,而不是 CQRS 或 Axon 的结果(截至 2018 年,该框架由 Axoniq 公司支持)
预先非常仔细地设计您的数据模型。尽管添加起来很容易,但对数据模型进行根本性更改可能非常困难。如果你在数据模型中犯了一个根本性的错误,你的应用程序可能性能不佳,甚至根本无法工作。例如,如果您选择树形数据模型,顶部有一个长期存在的聚合根,随着时间的推移,该聚合可能会变得非常大,因为它会累积越来越多的事件,并且可能需要很长时间来加载和存储。我不知道如果这种情况一直持续到聚合实例不再适合 RAM 会发生什么,但我想可能会很糟糕。不要那样做。
另一个陷阱(与事件溯源相关)是,经过多次修订后,推断聚合的状态会变得越来越困难,因为有时您不仅要记住代码今天做了什么,还要记住它的作用。过去做过。这无疑使重播(部分)事件存储以重建视图表成为一项不平凡的任务。
修复数据错误可能比使用“传统”设计更困难。您通常需要创建一个命令来更改应用程序的状态,而不是一个简单的 SQL 语句。如果数据中的错误是由错误的事件处理程序引起的,您通常可以修复错误,清除快照并让聚合事件重播。如果您的错误导致应用虚假事件,那么修复起来会更加麻烦。错误事件将保留在事件存储中,您可能必须应用一些新事件才能将数据恢复到正确状态,或者更改代码以忽略或修复它们的行为。
虽然框架本身写得足够好,但在现实世界的项目中使用它简直就是一场噩梦,而选择这个框架 imo 是导致该项目失败的主要因素。
该框架严重依赖事件源,这意味着所有状态更改都作为事件写入数据存储。因此,您拥有所有数据的历史参考。这很好,但是在您投入生产之后更改您的域是一个非常令人生畏的提议,特别是如果您以系统的“强大的可审计性”向客户推销
您不能让运维人员对数据库进行临时更改
该框架鼓励对数据进行非规范化,以至于有些人建议在应用程序中为每个视图创建一个表。这使您的应用程序极难维护,尤其是当原始开发人员离开时
如果不知何故您在其中一个事件处理程序中犯了错误,您唯一的选择是“重播”事件日志,这取决于您的数据大小可能需要很长时间。然而,用于此的工具是不存在的。重放可能会产生副作用,因此开发人员会害怕这样做
开发人员很容易搞砸使用这个框架。如果他们没有在事件中存储对域对象的更改,那么下次您重播事件时,您会大吃一惊。你应该存储三角洲的吗?绝对值?如果你不密切关注你的开发人员,你最终会得到两者,你会被f***ed
几乎没有采用这个框架,所以用谷歌搜索答案对你没有任何好处
尽管该框架还不支持分发,但它在编写时考虑到了它,因此使用 api 很痛苦。默认情况下,触发事件是异步的,如果您想检查执行命令是否引发异常,例如重复的用户名异常,您需要将侦听器传递给您的命令处理程序,这是一个未来,然后您等待未来的结果进来,处理任何检查的异常,interuptedexception等,然后你可以抓住未来抛出的异常。当然,命令可以引发哪些异常在 api 中并不明显。违背检查异常的目的
查看一些示例应用程序。我不知何故需要一个工作单元侦听器来创建地址簿应用程序?我的天啊...
我目前与一个团队在一个在线赌场平台上工作,今年夏天推出了我们的品牌Casumo 。域和平台是使用 Axon 框架构建的,到目前为止它已经为我们提供了可靠的服务。
无需构建命令处理、事件路由、事件溯源、快照等所需的所有基础设施,节省了大量时间,而且 API 非常好用。到目前为止,我们在框架中发现的一个错误已在 12 小时后的 .. 版本中修复,Allard 总是很快就新功能提出建议,并讨论利用框架来满足您的需求的方法。