在使用事件源聚合后端构建在DDD原则的环境中,如何将单独的聚合根(AR)相互通信?
例如,我有一个Facility聚合根(AR),它有一个负责创建BookingAR 的工厂方法.这Booking是PersonAR和FacilityAR 的时间敏感组合.A Person只能预订一个Facility.
在DDD中,我会保留对Bookingin Person和Personin的引用Facility.但是,当生成用于事件源的事件时,我认为尝试从后端处理事件反序列化将变得令人望而却步.因此,我只采用了对基于对象的值唯一id的引用.然而,这会带来一个新问题,当AR上的方法需要在另一个AR上调用另一个方法时 - 您如何处理这种情况?从域AR命中事件源存储库?
这种情况下的一般用例是什么?我接近这一切都错了吗?
我们目前正在评估CQRS和事件采购架构.我试图了解使用这种设计的维护含义是什么.我正在努力寻找答案的两个问题是:
1)如果在应用程序启动并运行一段时间后,有新的要求在ReadModel数据库上向ViewModel添加其他字段会发生什么?比如,CustomerList ViewModel上需要Customer Zip Code,而以前不是.因此,可以轻松地将额外列添加到ViewModel数据库,但是如何填充这些列?据我所知,唯一的方法是清除读取数据库,并从头开始重放所有事件以构建备份ReadModel数据库.但是,如果应用程序已启动并运行数月或数年(我们希望如此),该怎么办?这可能是数百万个要重播的事件,只是为了添加zipcode列的数据.
如果由于任何技术原因,ReadModel数据库不同步,或者我们想要添加新的ReadModel数据库,我也会有同样的担忧.看起来应用程序的版本越旧,使用的越多,更难和更昂贵的是获得最新的readmodel.或者我在某个地方错过了一招?像ReadModel快照一样?
2)如果在重放所有数百万个事件以构建备份读取数据库之后会发生什么,一些数据与预期不符(即看起来不对).据认为,在事件存储或非规范化例程中某处可能存在错误可能导致这种情况(似乎如果在编码中有一件事可以依赖,那就是错误).怎么去调试这个!这似乎是一项不可能的任务.或许,再次,我错过了一个技巧.
我有兴趣听到任何一直在运行这样的系统的人,以及维护和升级路径如何为您解决.
感谢您的任何时间和意见.
我已经转移到积极使用CQRS +事件采购的项目.从第一眼就看出它是按照所有这些书籍和博客实现的,但最后我意识到实施中究竟是什么样的暴躁.
这是CQRS架构:
本来我从这里拍了这张照片.
正如我们在图片中看到的那样,读取端从队列接收事件并将其逐个传递到不同的投影集(非规范化器)中,然后通过AddOrUpdate方法将结果的ViewModel保存到DB中.因此我从图片中了解到,denormalizer只能依赖事件本身加上来自读取端db的数据.例如:
另一个案例(计算一些项目的数量,说订单):
我们在项目中拥有的内容:我们仅将所有这些事件用作域模型中某些内容发生变化的通知程序.因此,我们做了什么:
我们在项目中使用的方法对我来说有点奇怪,但我看不出它的所有缺点.如果我们需要重建我们的读取端,我们添加"active"denormalizer,并在下次收到特定事件时,重新创建新的viewmodel.
如果我们使用书中的方法,我将不得不在我的系统之外的某个地方有一个单独的utils逻辑用于重建.我们需要什么:
所以我的问题是:
这里的正确方法是什么?
当我们拥有特定的唯一EntityID时,EventSourcing非常有效,但当我尝试从eventStore获取除特定EntityId以外的信息时,我很难过.
我正在使用CQS和EventSourcing.作为事件源的一部分,我们将事件存储在SQL表中作为列(EntityID(uniqueKey),EventType,EventObject(例如UserAdded)).
因此,在存储EventObject时,我们只是序列化DotNet对象并将其存储在SQL中,因此,所有与UserAdded事件相关的细节都将采用xml格式.我担心的是我想确保db中存在的userName应该是唯一的.
因此,在创建AddUser命令时,我必须查询EventStore(sql db)是否已在eventStore中存在特定的userName.因此,为此,我需要序列化事件存储中的所有UserAdded/UserEdited事件,并检查eventStore中是否存在请求的用户名.
但由于部分CQRS命令不允许查询,可能是因为Race条件.
所以,我尝试在发送AddUser命令之前只查询eventStore并通过序列化所有事件(UserAdded)获取所有UserNames并获取用户名,如果请求的用户名是唯一的,则命令其他方式抛出userName已经存在的异常.
与上述方法一样,我们需要查询整个数据库,并且每天可能有数十万个事件.因此,执行查询/反序列化将花费很多时间,这将导致性能问题.
我正在寻找任何更好的方法/建议维护用户名唯一通过从eventStore或任何其他方法获取所有userNames
除了Axon Framework之外,还有其他任何用于CQRS和事件采购的Java框架吗?我特意找
我一直在阅读有关CQRS+EventSoucing模式(我希望在不久的将来应用)以及我发现的所有平台和演示文稿的一个共同点,即为了恢复它而拍摄模型状态的快照,但这些模式中没有一个共享模式/这样做的策略.
我想知道你是否可以分享你在这件事上的想法和经验,特别是在以下方面:
TL; DR:您Snapshotting在CQRS+EventSourcing申请中的实施情况如何?优点和缺点?
我现在一直在使用Rx在一个应用程序中创建一个事件总线(想想CQRS/ES),它看起来效果很好.然而,在调查了一堆不同的Event Sourcing框架之后,我还没有看到Rx使用过一次.与基于反射/容器的调度程序相比,它看起来非常合适,但也许有一些我缺少的东西.我宁愿不花一大堆时间在一个有3个月的停顿的东西上.是不是有理由说Rx不合适?
谢谢,埃里克
我正在研究使用DDD + CQRS + EventSourcing制作应用程序,我在确定如何进行用户身份验证方面遇到了一些麻烦.
用户本质上是我的域的一部分,因为他们负责客户.我正在使用ASP.NET MVC 4,我希望只使用SimpleMembership.由于登录和授权用户是同步操作,如何在最终一致的架构中解决这个问题?
我是否必须滚动自己的auth系统,在读取端保留非规范化的auth表?如何处理这个的安全性?我最终会在我的事件存储区和视图表中存储密码哈希值吗?
这么多问题,如果有人能说清楚,我会非常感激:)
tldr; 你如何在EventSource应用程序中进行用户身份验证?
authentication authorization cqrs event-sourcing event-store
考虑以下针对Contact资源的粗粒度REST apis
POST /api/contacts
GET /api/contacts
GET /api/contacts/:id
PUT /api/contacts/:id
DELETE /api/contacts/:id
Run Code Online (Sandbox Code Playgroud)
考虑使用事件源作为联系人资源,即验证命令并存储事件.因此必须存储每个事件,包括每个字段级别的更改.
CreateContactCommand -> | Contact("john", "doe", 25) | -> ContactCreatedEvent
FirstNameChangeCommand -> | Contact("jane", "doe", 25) | -> FirstNameChangedEvent
LastNameChangeCommand -> | Contact("jane", "dear", 25) | -> LastNameChangedEvent
AgeChangeCommand -> | Contact("jane", "doe", 30) | -> AgeChangedEvent
Run Code Online (Sandbox Code Playgroud)
现在,将REST和EventSourcing结合起来.
做REST,客户端如何与上述标准REST API进行通信以进行字段级更改,以便在服务器端REST端点生成命令?
主要问题是,如何设计REST API以便它还可以支持最终支持事件的命令?
如果有人能够阐明这一点,我们将非常感谢你的帮助.
我理解命令和事件之间的区别,但在很多情况下,你最终会在2个基本相同的类之间进行冗余和映射(ThingNameUpdateCommand,ThingNameUpdatedEvent).对于这些简单的情况,您/您是否也可以将该事件用作命令?人们会将所有命令以及所有事件序列化到商店吗?对我来说似乎有点多余.
cqrs ×10
event-sourcing ×10
event-store ×2
api ×1
architecture ×1
axon ×1
java ×1
rest ×1
snapshot ×1
unique ×1