我的项目已经使用Spring和Spring Integration,这与Axon自己的要求很好地契合,但在我投入大量时间之前,我想知道是否有人有一些第一手的经验。特别是我对文档中不明显的可能存在的问题感兴趣。
完全不正确,它并不严重依赖事件溯源。该框架用于存储聚合的实现之一使用了事件溯源,但您也可以轻松地使用提供的类来使用标准关系模型。
但与事件溯源相比,后者更好一些。
因此,您拥有所有数据的历史记录。这很好,但是如果您在生产中更改了域,特别是如果您向客户出售了系统的“强大审计功能”,那么这将是一个非常令人生畏的建议。
我认为使用仅存储当前状态的标准关系模型并不容易得多。
该框架鼓励规范化数据,甚至有些人建议在应用程序中每个视图都使用一个表。这使得您的应用程序极其难以维护,特别是当原始开发人员离开时。
这与框架无关,而与使用的架构模式(CQRS)无关。而且,这里提到只有一个规范化器/视图是一个好主意,因为它保持了一个简单的对象。
因此,维护很容易,因为SQL请求/插入也很容易。所以这个论点不是很有力。怎么样一个视图使用了1000个表模型,在所有地方都有内部连接和复杂的SQL查询?
同样,CQRS有助于解决问题,因为基本上,视图数据只是从对应于该视图的表中选择*。
如果某种方式在其中一个事件处理程序中犯了错误,则您唯一的选择是“重新播放”事件日志,这取决于您的数据大小可能需要很长时间。但是目前没有相关工具。
我同意当前缺乏重放事件的工具,并且可能需要很长时间。但在理论上,只需重放部分事件而不是事件存储的所有内容即可。
重放事件会有副作用,所以开发人员变得不敢使用它。这是不正确的。对我来说,副作用意味着修改系统状态。在事件驱动的CQRS应用程序中,状态存储在事件存储中。重放事件不会修改事件存储。您可以对查询模型产生副作用,但如果出现错误,您仍然可以纠正它并重新播放事件。
如果开发人员没有将域对象的更改存储在事件中,则很容易在使用此框架时出错。下次重放事件时,您将会感到惊讶。
如果您误用或误解了架构、概念等,那么我同意您的观点。但也许问题不在框架本身。
我可以说,对于每个系统,我都会说它与框架本身无关。这就像说,“Java很糟糕,因为如果有人编写了hashCode和equals方法的错误实现,您可以弄乱一切。” 对于您评论的最后部分,我已经看到过使用Spring框架的helloworld示例。当然,在简单示例中完全没有用处。
请注意在评论中区分概念(CQRS + EventSourcing)和框架之间的区别。请区分开来。
由于您表示希望在项目中使用CQRS(我假设JVM是您的目标平台),因此我认为Axon框架是一个非常好的选择。
我曾在其上构建过相当复杂的交易平台(不,交易示例并不复杂),并且没有看到该框架的任何明显缺陷。
由于我使用EventSourcing,测试固定装置使得编写BDD风格的“given,when,then”测试非常容易。这使您可以将聚合视为黑盒子,集中精力检查在输入某个命令时是否产生了正确的事件集。
关于注意事项:在开始之前,请确保:
一些非Axon特定的要点:
从事件中重建视图存储是EventSourcing的一个概念,而不是Axon所特有的。但是我发现创建一个服务来向我发送特定聚合类型、聚合ID或某个事件类型的所有事件非常容易。
能够在项目启动后一年构建一个新的报表组件,并即时获得从项目启动开始的数据报告,这真是太棒了。
什么时候使用AxonFramework更多的是关于何时使用CQRS。为了回答这个问题,值得回到官方文档:http://www.axonframework.org/docs/1.4/introduction.html#d4e51
在我们的情况下,肯定是值得的。
这个问题的重点在于与Axon Framework相关的陷阱,而不是CQRS。这使得这个问题很难回答,因为Axon最初是一个相当忠实地实现了Eric Evans著名书籍的框架。
主要优势在于它确切地做到了它所说的:为您处理基于CQRS设计的难点:聚合、saga、事件源、命令处理程序、事件处理程序、BASE一致性等。当您遵循最佳实践时,您将获得高度响应和水平可扩展的应用程序。如果您将其与事件源配合使用,则您的数据完全可审计,并且至少在理论上,您可以确定应用程序在任何给定时间点的状态。没有提供此工具;您将不得不自己开发。
该框架的主要开发者非常亲近且在Java高性能和可伸缩计算方面极为有知识。他倾向于在邮件列表中回答每个问题,通常几小时内就会回复。
这既是优点,也是最大的缺陷:在2014年初,Axon Framework严重依赖于一个人。
我想提到的其他缺点可能更多是事件溯源而不是CQRS或Axon本身导致的。(截至2018年,该框架由Axoniq公司支持)
在设计您的数据模型时,请仔细考虑。虽然添加数据很容易,但对数据模型进行基本更改可能非常困难。如果在数据模型中犯了基本错误,则应用程序可能无法正常运行或表现不佳。例如,如果选择树形数据模型,在顶部有一个长时间存活的聚合根,则该聚合根可能会随着时间的推移累积越来越多的事件而变得非常庞大,并且它可能需要很长时间才能加载和存储。如果这种情况一直持续到某个聚合的实例无法适应RAM,则不知道会发生什么,但我想会很糟糕。不要这样做。
另一个陷阱(与事件溯源相关)是,经过多次修订后,聚合状态的推理可能变得越来越困难,因为你有时不仅需要记住代码今天的操作,还要记住它在过去的操作。这绝对使得重放(部分)事件存储以重建视图表成为一项非常棘手的任务。尽管该框架本身写得还不错,但在实际项目中使用却是一场噩梦,我认为选择这个框架是导致该项目失败的重要因素之一。
该框架严重依赖事件溯源,这意味着所有状态更改都会被写入数据存储作为事件。因此,您拥有所有数据的历史参考。这很好,但如果您已经在生产中销售了系统的“强大审计功能”,那么在更改域时将变得非常困难。
您不能让运维人员对数据库进行即兴更改
该框架鼓励对数据进行去规范化处理,甚至有人建议在应用程序中每个视图都有一个表。这使得您的应用程序非常难以维护,特别是当原始开发人员离开后。
如果您在其中一个事件处理程序中犯了错误,则唯一的选择是“重放”事件日志,这取决于您的数据大小可能需要很长时间。但是,这方面的工具不存在。重放可能会产生副作用,因此开发人员会害怕这样做。
使用这个框架时,开发者很容易出错。如果他们不将对域对象的更改存储在事件中,下次重放事件时就会出现意外情况。应该存储增量还是绝对值?如果你不监控开发者,最终你会同时遇到这两种情况,而且你会很惨。
实际上,这个框架几乎没有被采用,因此搜索答案并没有什么用处。
尽管该框架目前不支持分布式,但它是为此编写的,由于此原因,API 非常难以使用。默认情况下,触发事件是异步的,如果您想检查执行命令时是否引发了异常(例如,重复的用户名异常),则需要向命令处理程序传递一个侦听器,该侦听器是一个 future,然后等待 future 的结果返回,处理任何已检查的异常、InterruptedException 等,然后才能从 future 中获取抛出的异常。当然,从 API 中无法明确哪些异常可能会被命令引发,这违背了已检查异常的目的。
查看一些示例应用程序。我需要一个工作单元监听器来创建一个通讯录应用程序?天哪...
我目前与一个团队一起工作,开发一个在线赌场平台,我们将在今年夏天推出我们的品牌Casumo。该域名和平台是使用Axon Framework构建的,到目前为止,它已经为我们提供了可靠的服务。
没有必要构建所有需要的基础设施,如命令处理、事件路由、事件源等等,这样就节省了很多时间,而且API非常易于使用。到目前为止,我们在框架中发现的唯一一个错误在12小时后的发布中得到了修复,Allard总是很快地接受新功能的建议,并讨论如何利用框架来满足您的需求。