cqrs没有事件采购和LMAX风格单线程设计审查

时间:2012-11-04 14:05:35

标签: architecture cqrs

回顾一下我的计划,看看它是否可行。

我使用RDBMS并计划在没有事件源的情况下使用CQRS。我认为第一次尝试时事件采购有点先进,我不得不使用RDBMS。

基于任务的UI由许多命令组成,其中大多数命令不需要响应。

架构基本上是

            /---- RDBMS ( EF ) 
     IO  ops                 \
            |                 \
  Single threaded Domains   Fascade(DTO) Queries
            |                /
  Event/Command Dispatcher  /
             \             /
                MVC client 

单线程域不会相互通信,它们通过干扰器(基本上是环形缓冲区)与外界通信。

命令调度程序将外部事件和命令复制到磁盘,并在发生崩溃时重新加载它们。完成被明确标记(通过IO Ops)。

命令基本上是持久的(具有命令的事务范围),IO Ops层将获取所有事件并处理它们并在1个事务中标记命令完成。 (注意命令是通过日志服务而不是域来保留的,但它与IO opps进行通信,并将其与命令的工作相匹配)。如果命令失败并且其标记为持久(并非全部将存在),则可以重播该命令。 (它只有在拥有命令并且收到DoTransation消息时才会持久保存命令。)

命令调度程序通过破坏程序连接到域。

问题

  1. 我应该将整个域加载到内存(大约300 - 500 Meg)并运行吗?显然域只会在更新DB后更新。

  2. 将外部事件混合回命令调度程序是否可以(因此它被单个线程拾取并处理)。例如,事件成为一个命令。

  3. 对域和用户代码进行编码看起来很简单(我得到了一个很好的富域),至少从我正在研究的原型开始。是吗?

  4. 当域执行IO时,他们会向破坏者发送消息,并且可以

    • 指定命令guid,命令与a匹配 交易
    • 假设完成(射击并祈祷)
    • 提供一个回调命令,该命令被传递给命令调度程序,然后重新出现在域中。创建IO消息后,系统可以继续 当前命令或完成它并​​接收下一个命令 这够好吗?
  5. 系统在一个进程和共享内存中运行,但域资源只能由自己和1个线程访问。这样可以吗?

  6. 这是一个实验性的网状物。有什么想法吗?

1 个答案:

答案 0 :(得分:3)

首先,这种架构非常复杂。仔细检查项目的预计寿命是否值得所有建筑的初始投资。一句话:这个项目还会在5年或10年内支付账单吗?客户是否会允许您花费数月时间在架构上而不提供业务价值?

<强>问题

您没有提到您的命令调度程序的主机。无论这件作品是什么,它很可能是您应用程序中的瓶颈。除非它从非常高性能的队列(例如ZeroMQ)中提取消息,否则我认为您不需要环形缓冲区。在大多数情况下,队列都可以正常运行,而且要简单得多。

您的问题

我假设IO Ops表示事件/事件处理程序。我可能还有其他一些细微差别。

  1. 我怀疑这对Web应用程序是否有意义。如果数据库是性能瓶颈,则将域加载到内存中会很有用。根据应用程序的性能配置文件,它可能不是,并且管理所有这些线程的努力可能浪费开发人员的时间。 (主要是因为您必须确保在应用程序关闭时停止线程,或者应用程序永远不会关闭。)更新数据库后更新域的部分对我没有意义。您只想在启动时加载域。保存域的状态更改只能在下次启动时再次重新加载。我认为你需要在坚持之前改变域的状态。此外,如果数据库存在很大的瓶颈,我可能会异步保存状态。

  2. 我想你在这里缺少一些步骤。你可能想要把一个事件发送到一个命令并将其作为一个命令发送的地方听起来就像一个进程管理器(或者你喜欢的Saga)应该去的地方。业务流程很少像将事件转换为命令一样简单。例如。后续命令无法完成时会发生什么?或者,在发出命令之前需要发生多个事件。 (例如,OrderPlaced和PaymentReceived必须在发送ShipOrder之前发生)

  3. 域的困难部分通常是找出最合适的模型。如果您的域模型不适合实际域,则代码变得更加笨拙和复杂。除此之外,它实际上取决于您的域名。如果您的编程是微积分求解器,那么您可能正在考虑它。但是,一旦理解了商业逻辑,通常可以很好地编纂成文。

  4. 我真的不确定你要对交易位做什么。您是否尝试将多个命令包装到事务中?这可能代表了域名可以更好地建模或者您正在进行批处理。因为希望没有那么多命令被批量化,所以总是使用一个命令似乎是浪费。如果您的所有操作都是批处理的,并且批处理中的每个操作都只是设置单个字段,那么您真的错过了使用DDD和基于任务的UI的重点。

  5. 另见#1。如果需要这种性能水平,这应该没问题。您的域很可能作为接收命令的MVC应用程序上的单例托管在内存中。我假设您在访问共享内存时使用了正确的锁定技术。请注意,this site是此类主题的绝佳资源。特别是,不要被volatile关键字愚弄!

  6. 记住一切都是一种权衡。不要浪费大量时间开发不会真正使您的应用受益的架构。