CQRS之旅——旅程7(增加弹性和优化性能) (6)

团队还执行了一些额外的优化,这些优化在下面的实现细节部分中列出。团队在这一阶段的主要目标是优化系统,以确保UI呈现对用户有足够好的响应。我们还可以执行其他优化,这将有助于进一步提高性能,并优化系统使用资源的方式。例如,团队考虑的进一步优化是扩展视图模型生成器,该生成器填充系统中的各种读取模型。每个承载视图模型生成器实例的web角色都必须通过创建对Azure服务总线主题的订阅来处理写端发布的事件。

提高性能的进一步更改

除了在提高应用程序性能的旅程的最后阶段所做的更改之外,团队还确定了一些其他更改,这些更改将导致进一步的改进。但是,这个旅程的可用时间有限,所以不可能在V3版本中进行这些更改。

我们向应用程序的许多地方添加了异步行为,特别是在应用程序对Azure服务总线的调用中。然而,应用程序还有其他地方仍然执行阻塞调用。我们可以把那些同步调用改成异步:例如,当系统访问数据存储时。此外,我们将使用新的语言特性,如async和await。

通过采用存储转发设计,可以批量处理消息,并减少往返于数据存储的次数。例如,利用Azure服务总线会话将使我们能够从服务总线接收一个会话,从数据存储区读取多个条目、处理多个消息、一次保存到数据存储区,然后完成所有消息。

Markus(软件开发人员)发言:

通过接受一个服务总线会话,只要您保持锁,就只有一个会话的写入者和监听者。这减少了乐观并发异常。这种设计特别适合可用座位聚合的读和写模型。对于具有非常小分区的订单聚合关联的读模型,您可以从服务总线获取多个小会话,并在每个会话上使用存储转发方法。尽管系统中的读和写模型都可以从这种方法中受益,但是在我们期望数据最终是一致的、而不是完全一致的读模型中实现起来更容易。

该网站已经缓存了一些经常访问的读模型数据,但是我们可以将缓存的使用扩展到系统的其他区域。CQRS模式意味着我们可以将缓存视为最终一致的读模型的一部分,如果需要,还可以使用不同的缓存或根本不使用缓存来访问来自系统不同部分的读模型数据。

我们可以改进可用座位(SeatsAvailability)聚合的缓存快照实现。本章稍后将详细描述当前实现,其目的是始终检查事件存储,以查找在系统创建最新缓存快照之后到达的事件。当我们接收到要处理的新命令时,如果我们可以检查是否仍然使用与系统创建最新缓存快照时相同的服务总线会话,那么我们就可以知道事件存储中是否还有其他事件。如果会话没有更改,那么我们就知道自己是惟一的写入者,因此没有必要检查事件存储。如果会话已经更改,那么其他人可能已经将与聚合相关的事件写入到存储中,我们需要进行检查。

应用程序当前使用相同的优先级监听所有服务总线订阅上的所有消息。在实践中,有些信息比其他信息更重要。因此,当应用程序处于压力之下时,我们应该优先处理一些消息,以最小化对核心应用程序功能的影响。例如,我们可以识别某些愿意接受更多延迟的读模型。

Poe(IT运维人员)发言:

我们还可以在负载增加时使用自动缩放来扩展应用程序(例如使用Autoscaling Application Block),但是添加新实例需要时间。通过确定某些消息类型的优先级,我们可以在自动缩放添加资源的同时,继续在应用程序的关键领域提供性能。

当前实现使用随机生成的Guid作为存储在SQL数据库实例中的所有实体的键。当系统处于高负载下时,如果使用顺序Guid,特别是与聚集索引相关的Guid,它的性能可能会更好。有关顺序Guid的讨论,请参见The Cost of GUIDs as Primary Keys。

作为系统优化的一部分,我们现在在进程中处理一些命令,而不是通过服务总线发送它们。我们可以将此扩展到其他命令,并可能扩展到流程管理器。

在当前实现中,流程管理器处理传入消息,然后存储库尝试同步发送传出消息(如果服务总线由于节流行为引发任何异常,则使用 Transient Fault Handling Application Block重试发送命令)。我们可以替代使用一种类似于EventStoreBusPublisher类的机制以让流程管理器保存一个消息列表,这些消息必须在一个事务里连同它的状态一起发送,然后通知系统的另一部分,这个部分的职责是当有一些新消息准备好要发送的时候负责来发送消息。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpspxg.html