您可能无法在任何您想要的地方使用事务,因为云的分布式特性使得ACID(原子性、一致性、隔离性、持久性)事务在许多场景中不切实际。因此,您需要了解如何使用最终的一致性。例如,请参见第5章“准备发布V1版本”,以及第7章“添加弹性和优化性能”中减少UI延迟的部分章节。
您可能需要重新检查关于如何将应用程序组织到不同层的假设。例如,参见第7章“添加弹性和优化性能”中关于进程内同步命令的讨论。
您不仅必须考虑浏览器或内部环境与云之间的延迟,还必须考虑在云中运行的系统的不同部分之间的延迟。
您必须考虑到瞬时错误,并了解不同的云服务可能如何实现节流。如果您的应用程序使用几个可能被节流的云服务,那么您必须协调应用程序如何处理不同服务在不同时间进行节流。
Markus(软件开发人员)发言:
我们发现,代码中只有一个总线抽象,这掩盖了这样一个事实,即有些消息是在本地进程内处理的,有些消息是在不同的角色实例中处理的。要查看这是如何实现的,请查看ICommandBus接口以及CommandBus和SynchronousCommandBusDecorator类。第七章“增加弹性和优化性能”包括了对SynchronousCommandBusDecorator类的讨论。
在我们的旅程开始时,有人警告我们,尽管CQRS模式看起来很简单,但实际上它要求您在考虑项目的许多方面时进行重大的转变。我们在旅途中的经历再次证明了这一点。您必须准备抛弃许多假设和预先设想的想法,在开始充分理解从模式中获得的好处之前,您可能需要先在几个限界上下文中实现CQRS模式。
这方面的一个例子是最终一致性的概念。如果您来自关系数据库背景,并且已经习惯了事务的ACID属性,那么在系统的所有级别上接受最终的一致性并理解其含义是一个很大的步骤。第5章“准备发布V1版本”和第7章“添加弹性和优化性能”都讨论了系统不同领域的最终一致性。
除了与您可能熟悉的不同之外,还没有一种正确的方法来实现CQRS模式。由于我们对模式和方法的不熟悉,我们在功能块上做了更多错误的开始,并且对所需的时间估计很差。随着我们对这种方法越来越熟悉,我们希望能够更快地确定如何在特定情况下实现模式,并提高我们估算的准确性。
Markus(软件开发人员)发言:
CQRS模式在概念上很简单,而细节才决定成败。
我们花了一些时间来理解CQRS方法及其含义的另一种情况是在限界上下文之间的集成期间。第5章“准备发布V1版本(https://www.cnblogs.com/angrymoto/p/cqrs-journey-day5.html)”详细讨论了团队如何处理会议管理与订单和注册上下文之间的集成问题。这部分旅程揭示了一些额外的复杂性,当您使用事件作为集成机制时,这些复杂性与限界上下文之间的耦合级别有关。我们的假设是,事件应该只包含关于聚合或限界上下文中变化的信息,但事实证明这种假设是没有帮助的,事件可以包含对一个或多个订阅者有用的附加信息,并有助于减少订阅者必须执行的工作量。
CQRS模式为如何划分系统引入了额外的思考。您不仅需要考虑如何将系统划分为层,还需要考虑如何将系统划分为限界上下文,其中一些上下文将包含CQRS模式的实现。在旅程的最后阶段,我们修改了关于层的一些假设,将一些处理从最初完成处理的工作者角色引入到web角色中。在第7章“增加弹性和优化性能”中讨论了如何在进程中发送和处理命令。应该根据领域模型将系统划分为限界上下文,每个限界上下文都有自己的领域模型和通用语言。一旦确定了限界上下文,就可以确定在哪些限界上下文中实现CQRS模式。这将影响如何以及在何处需要实现这些隔离限界上下文之间的集成。第二章“[分解领域]”介绍了我们对Contoso会议管理系统的所作的决策。