2

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

我正在使用 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)并运行吗?显然域只会在数据库更新后更新。

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

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

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

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

这是一个实验性的混合网格。有什么想法吗?

4

1 回答 1

3

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

问题

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

你的问题

我假设 IO Ops 是指事件/事件处理程序。可能还有其他我没有注意到的细微差别。

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

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

  3. 域的难点通常是找出最合适的建模方式。如果您的域模型不适合实际域,那么代码会变得更加笨拙和复杂。除此之外,这实际上取决于您的域。如果您对微积分求解器进行编程,那么您可能会喜欢它。但是通常,一旦理解了业务逻辑,就可以将其编成合理的代码。

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

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

请记住,一切都是权衡。不要浪费大量时间开发对您的应用程序没有真正好处的架构。

于 2013-01-08T00:51:34.410 回答