AWS 上的事件驱动架构
2021年9月,Duckbill Group首席云经济学家Corey Quinn发表了《解开AWS计费之谜的关键在于架构》一文,他的一些观点让我深有同感。其中一点,有时被人们忽视,那就是成本即架构。
例如,如果您在构建应用程序时因为 SQS 无法满足您的吞吐量需求或成本过高而未使用它,那么这种情况在几周前已经发生了改变。SQS 现在几乎可以实现无限吞吐量,而成本仅为发布时的 3.6%。
3.6%这个数字是因为Zack Kanter的笔误。实际上,价格比2006年下降了99.4%,也就是说现在的价格只有原来的0.6%。你现在支付的价格甚至不到几年前的1%!
失去联系
在现代软件架构中,尤其是在Web或分布式领域,有一个广为人知的通用建议,那就是提倡松耦合。当然,这是一个崇高的目标,但耦合的类型有很多种,例如时间耦合,它指的是基于时间的依赖关系,例如协作系统组件、顺序操作或需要其他组件才能完成的请求或其他操作。还有空间耦合,例如无需了解协作应用程序在网络中的具体位置,并提供故障转移机制,例如负载均衡器、发布/订阅等。当然,平台耦合在无服务器领域比在云领域更为常见,它指的是使用来自供应商或平台的专有协议和组件。
但正如前文所述,耦合是一个多维度的函数,而不仅仅是“紧密”或“松散”这种二元选择。我们始终都在权衡取舍。
事件驱动架构是一种流行的分布式异步架构风格,用于构建高度可扩展和高性能的应用程序。它也具有很强的适应性,既可用于小型应用程序,也可用于大型复杂应用程序。事件驱动架构由解耦的事件处理组件构成,这些组件异步接收和处理事件。它可以作为独立的架构风格使用,也可以嵌入到其他架构风格中(例如事件驱动的微服务架构)。——《
软件架构基础》,Mark Richards 和 Neal Ford 著
受Eric Evans 的《领域驱动设计:解决软件核心的复杂性》以及Vaughn Vernon 的《领域驱动设计精粹》和《领域驱动设计实现》的启发,软件建模和开发的一种方法是处理限界上下文。我们可以映射并创建服务、应用程序和系统,从而更好地解决问题。为了整合所有这些,领域事件模式应运而生。
事件成为在有界上下文集成中共享状态变更信息的主要机制。领域事件是不可变的,并且具有自描述性。事件通过提供业务上下文赋予其所承载的数据意义。它们并非数据传输对象或变更数据捕获。这些只是状态/状态变更的表示,并不能反映系统的实际行为。
事件是一个量子,它是描述系统中事物的单位。它可以是一个简单的 JSON 对象,如下所示:
{
"eventId": 61452,
"event": "OrderPlaced",
"createdAt": "2021-10-07"
}
例如,对于此事件,不同的域可以决定是否采取行动。我们可能有一个库存域、一个包裹域,以及一个会向用户发送订单邮件的服务,每个域都会根据自身情况处理该事件,我们可以根据需要添加和应用任意数量的服务和应用程序。我们将所有这些事件发布到“总线”,在 AWS 中,这是通过Amazon EventBridge实现的。作为一名 CDK 爱好者,我甚至可以用几行 TypeScript 代码创建自己的基础设施即代码。
import * as cdk from '@aws-cdk/core';
const stack = new stack();
const bus = new EventBus(stack, 'bus', {
eventBusName: 'MyCustomEventBus'
});
bus.archive('MyArchive', {
archiveName: 'MyCustomEventBusArchive',
description: 'MyCustomerEventBus Archive',
eventPattern: {
account: [stack.account],
},
retention: cdk.Duration.days(365),
});
利用上面的代码,您可以配置自定义事件总线,并创建所有事件的 365 存档。如有需要,这些存档可用于审计或事件重放。即使在我的示例中,假设用户想要取消订单,我们也不会删除之前的事件。不同的域需要处理新事件,以便撤销操作或分析操作原因等等。
{
"eventId": 61456,
"event": "OrderCancelled",
"createdAt": "2021-10-07"
}
或许还会发送另一封邮件来确认取消,库存管理团队也需要调整工作流程等等。现在,或许还需要向客户关系管理系统 (CRM) 提供数据,以了解客户转化后取消订单的原因。
耦合始终存在。但我们可以利用这些服务进行协调,构建高响应性、高可用性和高健壮性的架构。您可以将 EventBridge 与Lambda、SNS、SQS和Step Functions结合使用,很快就能拥有可以轻松扩展和缩减的系统。如果配置得当,还能大幅优化成本,因为我们目前某些服务和应用程序需要 24/7 全天候运行在服务器上,但有时只需要在特定事件发生时才激活即可。
目前我正在进行一个事件驱动型开发项目,我非常喜欢这种思维模式,以及它为开发者和组织带来的体验。我们很快就会用到领域驱动设计(DDD)中的“通用语言”。就这套工具而言,没有其他云平台比AWS更合适、更可靠了。
推荐阅读的书籍
-
《构建事件驱动型微服务:大规模利用组织数据》(作者:Adam Bellemare)一书为事件驱动型架构带来了诸多价值,涵盖了架构模式和应用模式两方面。
-
《Python架构模式:实现测试驱动开发、领域驱动设计和事件驱动微服务》(Architecture Patterns with Python: Enabling Test-Driven Development, Domain-Driven Design, and Event-Driven Microservices),作者Harry Percival和Bob Gregory。Python并非我工作中的主要语言,甚至也不是我的首选语言,但我从这本书中获益匪浅。因为本书着眼于架构模式,所以如果你不使用Python,千万不要被书名误导。这本书的内容非常丰富!
追随英雄
是的,他们确实是英雄。
本·埃勒比
@EllerbyBen
对我来说,他的一篇文章对我的工作帮助很大,也开启了许多可能性:EventBridge Storming——如何构建最先进的事件驱动型无服务器架构。他写了很多关于无服务器转型概念的博客,这个术语我也采用了。
Sheen Brisals
@sheenbrisals
经常在Medium上写博客。上一篇文章是《如何使用 AWS Step Functions、任务令牌和 Amazon EventBridge 构建更好的编排》!