旅程7:增加弹性和优化性能 到达旅程的终点:最后的任务。 “你不能飞的像一只长着鹪鹩翅膀的老鹰那样。”亨利·哈德逊
我们旅程的最后阶段的三个主要目标是使系统对故障更具弹性,提高UI的响应能力,并确保我们的设计是可伸缩的。加强系统的工作主要集中在订单和注册限界上下文中的RegistrationProcessManager类。性能改进工作的重点是当订单创建时UI与领域域模型的交互方式。
本章的工作术语定义:本章使用了一些术语,我们将在下面进行描述。有关更多细节和可能的替代定义,请参阅参考指南中的“深入CQRS和ES”。
命令(Command):命令是要求系统执行更改系统状态的操作。命令是必须服从(执行)的一种指令,例如:MakeSeatReservation。在这个限界上下文中,命令要么来自用户发起请求时的UI,要么来自流程管理器(当流程管理器指示聚合执行某个操作时)。命令由单个接收方只处理一次,命令要么通过命令总线(command bus)传递给接收方,要么直接在进程中传递。如果是通过总线传递的,则该命令是异步发送的,在进程中传递,命令将同步发送。
事件(Event):一个事件,比如OrderConfirmed,描述了系统中发生的一些事情,通常是一个命令的结果。领域模型中的聚合引发事件。事件也可以来自其他限界上下文。多个订阅者可以处理特定的事件。聚合将事件发布到事件总线。处理程序在事件总线上注册特定类型的事件,然后将事件传递给订阅服务器。在订单和注册限界上下文中,订阅者是流程管理器和读取模型生成器。
快照(Snapshots):快照是一种可以应用于事件源的优化。在重新还原(rehydrated)聚合时,不需要重播与聚合相关的所有持久化事件,而是加载聚合状态的最新副本,然后只重播保存快照后持久的事件。通过这种方式,可以减少必须从事件存储里加载的数据量。
幂等性(Idempotency):幂等性是一个操作的特性,这意味着该操作可以多次应用而不改变结果。例如,“将x的值设置为10”的操作是幂等的,而“将x的值加1”的操作不是幂等的。在消息传递环境中,如果消息可以多次传递而不改变结果,则消息是幂等的:这可能是因为消息本身的性质,也可能是因为系统处理消息的方式。
最终一致性(Eventual consistency):最终一致性是一个一致性模型,它不能保证立即访问更新的值。对数据对象进行更新后,存储系统不保证对该对象的后续访问将返回更新后的值。然而,存储系统确实保证,如果在足够长的时间内没有对对象进行新的更新,那么最终所有访问都可以返回最后更新的值。
架构该应用程序旨在部署到Microsoft Azure。在旅程的这个阶段,应用程序由两个角色组成,一个包含ASP.Net MVC Web应用程序的web角色和一个包含消息处理程序和领域对象的工作角色。应用程序在写端和读端都使用Azure SQL DataBase实例进行数据存储。在某些地方,应用程序还在写端使用Azure table,在读端使用Azure blob来存储数据。应用程序使用Azure服务总线来提供其消息传递基础设施。下图展示了这个高级体系结构。
在研究和测试解决方案时,可以在本地运行它,可以使用Azure compute emulator,也可以直接运行MVC web应用程序,并运行承载消息处理程序和领域域对象的控制台应用程序。在本地运行应用程序时,可以使用本地SQL Server Express数据库,并使用一个在SQL Server Express数据库实现的简单的消息传递基础设施。
有关运行应用程序的选项的更多信息,请参见附录1“发布说明”。
增加弹性在旅程的这个阶段,团队研究了加强RegistrationProcessManager类的方法。该类负责管理订单和注册上下文中的聚合之间的交互,并确保它们彼此一致。如果要将限界上下文作为一个整体来维护其一致状态,那么流程管理器必须能够适应各种各样的故障条件。
通常,流程管理器接收传入的事件,然后在限界上下文内部基于流程管理器的状态发出一个或多个命令到聚合。当流程管理器发出命令时,它通常会更改自己的状态。
订单和注册限界上下文包含RegistrationProcessManager类。此流程管理器在此限界上下文中和支付限界上下文中负责通过路由事件和命令协调聚合的活动。因此,流程管理器负责确保这些限界上下文中的聚合正确地彼此同步。