偶尔连接系统中的EventSourcing:如果有两台服务器怎么办?

时间:2016-12-23 08:08:18

标签: event-sourcing data-synchronization neventstore occasionallyconnected

我最近试图解决这个问题。

单一服务器方案

您的客户端偶尔会连接到单个服务器。

我最近再次看了greg youngs video on occasionally connected systems on skillsmatter.com

在那里,他说处理它的最佳方法是:

  • 您有一个使用事件流的客户端。
  • 客户端将其在队列中执行的所有命令保留
  • 当服务器再次可用时,客户端会推送所有命令并再次下载生成的事件 (本地,客户端删除本地发出的事件,因为服务器是单一的事实来源

现在这一切都很好,但我有一个更复杂的情况 - 一个有两个服务器:测试和生产

mutli server secnario

  • 因此客户端用于创建某种模板
  • 然后连接到测试服务器并推送其命令=>我们在测试服务器上有一个新的模板版本
  • 客户端会不时重新连接到测试服务器并更改模板
  • 但是,有时候,tempalte将发布到Production服务器。

您还可以将此视为git merge场景,您希望将所有更改从分叉远程存储库A推送到原始远程存储库B.

问题是:

  1. 一旦客户端将其更改推送到测试环境,命令就会消失 - 那么它如何将任何更改推送到生产环境......
  2. 另外:可能会使用其他用户将新模板实际发布到Production。 (例如,因为发布是由一个人而不是开发人员完成的)
  3. 所以我猜这个问题基本上有两个解决方案: a)保留命令流并将其下载到客户端 - 但这与在事件采购系统中仅存储事件的事实相冲突 b)有一种机制可以从已经提交的事件中重新创建命令。 这样,客户端可以查看生产中的模板版本,以查看尚未在那里发出的事件。然后它相应地创建命令并执行它们。

    我的问题:

    1. 我想这里只有b是可行的选择吗?
    2. 选项b是否违反了事件来源和/或cqrs的任何规则/原则?
    3. 还有其他甚至更好的方法吗?
    4. 谢谢你们的想法!

      更新

      感谢您分享您的想法。但似乎我必须澄清一些事情 - 测试与制作的事情。

      让我们假设我们正在构建一些像salesforce这样的应用程序框架:您可以 - 通过使用指向和单击 - 使用其实体和工作流等来定义您的应用程序。 当然,您可以在单独的沙箱环境中执行此操作。 当您完成第一个应用程序版本后,您将需要将其移至生产服务器,以便您的用户可以实际使用您构建的应用程序"。

      现在考虑以下内容:在生产中,您意识到,存在一个小错误,您可以立即修复它。然后,您希望将这些更改传回测试环境。

      所以现在问题是:真正的来源是什么?

      我喜欢抱怨git,因为大多数开发者都知道。 基本上我可以看到我有两个选择:

      1. git rebase
      2. 其中一个环境是记录簿。所以在那种情况下,我必须收集所有命令,一旦我更新生产,我就会推送命令。 这就像 git rebase

        1. git merge
        2. 让我们假设这两个系统都是"记录簿"。在这种情况下,我需要同步测试环境中发生的事件和生产环境中发生的事件(因此我在测试和生产中获得了相同的应用程序定义) 因此,来自Test的事件不仅仅附加到生产的事件流,而是按照它们实际发生的顺序在生产事件流中排序。 这就像 git merge

          我个人更喜欢 git merge 选项,因为它会在两个系统中产生完全相同的事件顺序。 当然,这将允许偶尔连接的客户端使用相同的方法进行分布式协作: 假设我们在Test中定义并使用此Event Sourcing方法发布到Production的应用程序随后被多个偶尔连接的客户端用于实际收集数据。 现在,多个客户端可以在相同的聚合根同步上彼此协同工作(如在peer2peer系统中),同时仍保持相同的事件流顺序。

          然而,问题可能是客户端将事件e1同步到服务器,但此事件对应的聚合器已经处理了稍后发生的事件e2。所以事件处理会出现故障。

          所以我的问题是:这个" git merge"是否有任何明显的缺点?

1 个答案:

答案 0 :(得分:1)

我认为你对你的记录/真相的定义纠缠在你的情况中。

如果 production 是记录簿,那么应该发送命令。在这种情况下,测试实例在几个方面与客户端实例类似;它变成了一个可以尝试外出的沙箱,但它实际上可能并不代表真相"当谈到推动下一阶段的事情。因此,您将命令排在队列中,并最终将这些命令传递给生产实例。

如果 test 是这些更改的记录簿,那么您不能与生产共享命令,而是共享事件(或者可能是投影,具体取决于哪种型号更适合您的实际使用情况)。这有点类似于使用微服务: test 是支持发送给它的命令的微服务,而生产是一个单独的微服务,可以响应来自 test 的事件 - 在其他单词,生产取决于测试中的阅读模型。

回顾Udi Dahan对services所说的话可能有助于澄清事情

  

服务是特定业务能力的技术权威。   任何数据或规则必须仅由一项服务拥有。

我的猜测,基于您使用" test"和#34;生产",是生产系统没有权力改变正在推动测试的数据;它只是消耗了该数据的视图。这使你直接回到单个服务器(实际上是:单本记录)用例。