Markus(软件开发人员)发言:
负责发送消息的系统部分可以异步发送消息。它还可以为发送消息实现动态节流,并动态控制要使用多少个并行发送器。
我们当前的事件存储实现是:为存储在事件存储里的每一个事件发布一个单独的,小的消息到消息总线上。我们可以将其中一些消息组合在一起,以减少服务总线上的I/O操作总数。例如,大型会议的可用座位(SeatsAvailability)聚合实例发布大量事件,订单(Order)聚合以突发方式发布事件(当创建订单(Order)聚合时,它同时发布OrderPlaced事件和OrderTotalsCalculated事件)。这还将有助于减少系统中的延迟,因为目前,在那些顺序很重要的场景中,我们必须在发送下一个事件之前等待一个事件已被发送的确认。将事件序列分组到一条消息中意味着我们不需要在发布单个事件之间等待确认。
增强可伸缩性的进一步更改Contoso会议管理系统允许您部署web和工作者角色的多个实例,从而扩展应用程序以处理更大的负载。然而,该设计并不是完全可伸缩的,因为系统的其他一些元素,例如消息总线和数据存储对最大可实现的吞吐量有限制。本节概述了我们可以对系统进行的一些更改,以删除其中的一些约束,并显著提高系统的可伸缩性。这次旅程的可用时间有限,所以没能在V3版本中进行这些更改。
数据分区:系统在不同的分区中存储不同类型的数据。在启动代码中,您可以看到不同的限界上下文如何使用不同的连接字符串连接到SQL数据库实例。但是,每个限界上下文目前使用一个SQL数据库实例,我们可以将其更改为使用多个不同的实例,每个实例都包含系统使用的特定数据集。例如,订单和注册限界上下文可以为不同的读取模型使用不同的SQL数据库实例。我们还可以考虑使用federations特性来使用分片扩展一些SQL数据库实例。
“数据持久性是大多数可伸缩SaaS企业面临的最困难的技术问题。”
-Evan Cooke, CTO, Twilio,Scaling High-Availability Infrastructure in the Cloud
Jana(软件架构师)发言:
在系统将数据存储在Azure表存储中的地方,我们选择用键对数据进行分区以实现可伸缩性。作为使用SQL数据库federations对数据进行切分的替代方法,我们可以将SQL数据库实例中当前的一些读模型数据移动到Azure表存储或blob存储中。
进一步划分服务总线:通过为不同的事件发布者使用不同的Topic,我们已经对服务总线进行了划分,以避免在系统发送的消息量接近服务总线能够处理的最大吞吐量时进行节流。我们可以使用多个相似的Topic来进一步划分主题,并通过循环监听它们来分担负载。有关此方法的详细描述,请参见Abbott和Fisher在Scalability Rules: 50 Principles for Scaling Web Sites, (Addison-Wesley, 2011)中的第11章"Asynchronous Communication and Message Buses"
存储和转发:我们在前面关于性能改进的小节中介绍了存储和转发设计。通过批处理多个操作,您不仅减少了到数据存储的往返次数,并减少了系统中的延迟,还增强了系统的可伸缩性,因为发出更少的请求可以减少对数据存储的压力。
监听节流指示器并对其作出反应:目前,系统使用Transient Fault Handling Application Block来检测瞬时错误条件,比如从Azure服务总线、SQL数据库实例和Azure表存储中检测节流指示器。系统使用Block在这些场景中实现重试,通常使用指数回退策略。目前,我们在单个订阅级别使用动态节流,但是,我们希望修改它来对特定主题的所有订阅执行动态节流。类似地,我们希望在SQL数据库实例级和Azure存储帐户级实现动态节流。
Jana(软件架构师)发言:
在应用程序里实现动态节流的一个例子是从服务阻止节流,看EventStoreBusPublisher SubscriptionReceiver, SessionSubscriptionReceiver类是怎样使用DynamicThrottling类来管理他们所使用的并行程度来发送或接收消息的。