我们使用机器学习技术将英文博客翻译为简体中文。您可以点击导航栏中的“中文(简体)”切换到英文版本。
将无服务器、事件驱动的架构扩展到现有的容器工作负载
这篇文章由南非首席专家迪拉吉·马哈帕特罗、南澳首席专家萨莎·穆勒林以及整合服务WW负责人艾米丽·谢伊撰写。
许多无服务器服务自然适合
在构建事件驱动架构时,您可能有现有服务可以与新架构集成,理想情况下,无需对这些服务进行重大重构更改。由于服务通过事件进行通信,因此将应用程序扩展到新的和现有的微服务是使用 EDA 进行构建的主要好处。你可以用不同的编程语言编写这些微服务,也可以在不同的计算选项上运行。
事件驱动架构示例概述
在这种情况下,结算服务是一个
Spring Boot 应用程序公开了一个 REST 端点,该端点接受 POST 请求。它应用结算业务逻辑,并在数据库中为汽车保险索赔创建结算记录。您的目标是使用专为索赔处理而设计的全新 EDA 应用程序进行结算,而无需重新设计架构或重写。客户、索赔、欺诈、文档和通知是下图中以蓝色方框显示的其他域:
项目结构
该应用程序使用
以下项目结构使您能够构建不同的
您可以将更高级别的 CDK 结构分解为以下相应的域:
应用程序和基础架构代码存在于每个域中。这种项目结构创建了一种无缝的方式,可以在不影响其他业务领域的情况下,通过其应用程序和基础设施代码添加结算等新域。
在前面的结构中,你可以在 claims-processing-stack.ts 中使用settlement-service.ts CDK结构:
const settlementService = new SettlementService(this, "SettlementService", {
bus,
});
SettlementService 结构唯一需要的信息是在索赔处理堆栈中创建的 EventBridge 自定义事件总线资源。
要运行示例应用程序,请按照示例应用程序的 README 文件 中的
现有容器工作负载
结算域为组织的其他部门提供 REST 服务。Docker 容器化 Spring Boot 应用程序使用 亚马逊云科技 Fargate 在亚马逊 ECS 上运行。以下序列图显示了从外部 REST 客户端到服务的同步请求-响应流:
-
外部 REST 客户端通过内部
应用程序负载均衡器 (ALB) 前面的HTTP API 进行 POST /结算调用。 - SettlementController.java 代表参加 SettlementService.java。
- 结算服务应用业务逻辑并调用结算存储库以保持数据持久性。
- 结算存储库将该项目保留在结算 DynamoDB 表中。
对 HTTP API 端点的请求如下所示:
curl --location <settlement-api-endpoint-from-cloudformation-output> \
--header 'Content-Type: application/json' \
--data '{
"customerId": "06987bc1-1234-1234-1234-2637edab1e57",
"claimId": "60ccfe05-1234-1234-1234-a4c1ee6fcc29",
"color": "green",
"damage": "bumper_dent"
}'
来自 API 调用的响应是:
您可以在此处了解有关在
扩展事件的容器工作负载
要集成结算服务,您必须更新服务以异步接收和发出事件。结算服务的核心逻辑保持不变。当您提出索赔、上传损坏的汽车图像且应用程序未检测到任何文件欺诈时,结算域会订阅 Fraud.Not.Detected 事件并应用其业务逻辑。结算服务在应用业务逻辑后会重新发出事件。
以下序列图显示了与 EDA 配合使用的新结算接口。结算服务订阅制作人发布的事件。在这里,事件制作者是将事件置于 EventBridge 自定义事件总线中的欺诈服务。
- 制作者向 EventBridge 自定义事件总线发出 Fraud.Not.Tectived 事件。
- EventBridge 评估结算域提供的规则,并将事件负载发送到目标 SQS 队列。
-
SubscriberService.java 在 SQS 队列中 轮询新消息。 - 在消息上,它将消息正文转换为结算服务接受的输入对象。
- 然后,它将呼叫委托给结算服务,类似于SettlementController在REST实现中的工作方式。
- 结算服务应用业务逻辑。流程就像从 7 到 10 的 REST 用例。
-
收到来自结算服务的回复后,订阅服务会转换响应,将事件发布回事件总线,事件类型为 Settlement.Financed。
架构的其余部分消耗了这个 Settle
ment.Financed
事件。
使用 EventBridge 架构注册表和发现
Schema 强制执行生产者与消费者之间的合同。每次事件到达时,消费者都期望事件负载的确切结构。EventBridge 提供
在下载代码绑定并在存储库中使用它们之前,在 EventBridge 中启用架构发现。
代码绑定提供了一个编组器,可以将传入的事件从 SQS 队列解组为
您可以选择 IDE 来下载代码绑定。
采用 REST 和事件驱动架构的结算服务的最终架构如下所示:
过渡到完全由事件驱动的状态
凭借处理事件的新功能,Spring Boot 应用程序现在通过不同的接口运行相同的业务逻辑,同时支持 REST 端点和事件驱动架构。在此示例场景中,随着事件驱动架构的成熟以及组织其他部门的采用,使用 POST 端点保存结算的需求可能会减少。将来,您可以弃用端点并完全依赖来自 SQS 队列的轮询消息。
你从使用 ALB 和 Fargate 服务
const loadBalancedFargateService = new ecs_patterns.ApplicationLoadBalancedFargateService(
this,
"settlement-service",
{
cluster: cluster,
taskImageOptions: {
image: ecs.ContainerImage.fromDockerImageAsset(asset),
environment: {
"DYNAMODB_TABLE_NAME": this.table.tableName
},
containerPort: 8080,
logDriver: new ecs.AwsLogDriver({
streamPrefix: "settlement-service",
mode: ecs.AwsLogDriverMode.NON_BLOCKING,
logRetention: RetentionDays.FIVE_DAYS,
})
},
memoryLimitMiB: 2048,
cpu: 1024,
publicLoadBalancer: true,
desiredCount: 2,
listenerPort: 8080
});
为了适应 EDA,您需要更新资源以改装 SQS 队列以接收消息,并将 EventBridge 改造为放置事件。向 Applicati
environment: {
"SQS_ENDPOINT_URL": queue.queueUrl,
"EVENTBUS_NAME": props.bus.eventBusName,
"DYNAMODB_TABLE_NAME": this.table.tableName
}
授予 Fargate 任务权限,将事件放入自定义事件总线并使用来自 SQS 队列的消息:
props.bus.grantPutEventsTo(loadBalancedFargateService.taskDefinition.taskRole);
queue.grantConsumeMessages(loadBalancedFargateService.taskDefinition.taskRole);
当您将结算服务过渡到完全由事件驱动时,您不再需要 HTTP API 端点和 ALB,因为 SQS 是事件的来源。
更好的选择是使用
const queueProcessingFargateService = new ecs_patterns.QueueProcessingFargateService(this, 'Service', {
cluster,
memoryLimitMiB: 1024,
cpu: 512,
queue: queue,
image: ecs.ContainerImage.fromDockerImageAsset(asset),
desiredTaskCount: 2,
minScalingCapacity: 1,
maxScalingCapacity: 5,
maxHealthyPercent: 200,
minHealthyPercent: 66,
environment: {
"SQS_ENDPOINT_URL": queueUrl,
"EVENTBUS_NAME": props?.bus.eventBusName,
"DYNAMODB_TABLE_NAME": tableName
},
capacityProviderStrategies: [
{
capacityProvider: 'FARGATE_SPOT',
weight: 2,
},
{
capacityProvider: 'FARGATE',
weight: 1,
},
],
});
此模式根据队列深度抽象化 Fargate 服务的自动扩展行为。
运行应用程序
要测试应用程序,请在初始设置 后按照
{
"version": "0",
"id": "e2a9c866-cb5b-728c-ce18-3b17477fa5ff",
"detail-type": "Settlement.Finalized",
"source": "settlement.service",
"account": "123456789",
"time": "2023-04-09T23:20:44Z",
"region": "us-east-2",
"resources": [],
"detail": {
"settlementId": "377d788b-9922-402a-a56c-c8460e34e36d",
"customerId": "67cac76c-40b1-4d63-a8b5-ad20f6e2e6b9",
"claimId": "b1192ba0-de7e-450f-ac13-991613c48041",
"settlementMessage": "Based on our analysis on the damage of your car per claim id b1192ba0-de7e-450f-ac13-991613c48041, your out-of-pocket expense will be $100.00."
}
}
正在清理
该堆栈创建自定义 VPC 和其他相关资源。一定要在使用后清理资源,以避免持续运行这些服务的成本。要清理基础架构,请按照示例应用程序中显示的
结论
该博客介绍了一种将在 亚马逊云科技 Fargate 上运行的现有容器工作负载与新的事件驱动架构相集成的方法。您可以使用 EventBridge 将使用不同的计算技术、语言和框架构建的不同服务相互分离。使用 亚马逊云科技 CDK,您可以获得相互分离的建筑服务的模块化。
这篇博客展示了一种不断演变的架构,它允许您以最少的更改对现有容器工作负载进行现代化改造,这仍然为您提供了在 亚马逊云科技 上使用无服务器和 EDA 进行构建的额外好处。
事件驱动方法和 REST 方法之间的主要区别在于,一旦制作者发出事件,你就会解除对其的封锁。订阅该事件的结算域中的事件制作者是松散耦合的。业务功能保持不变,无需进行大量的重构或重新架构工作。有了这些敏捷性的提高,你可以更快地进入市场
详细了解
*前述特定亚马逊云科技生成式人工智能相关的服务仅在亚马逊云科技海外区域可用,亚马逊云科技中国仅为帮助您发展海外业务和/或了解行业前沿技术选择推荐该服务。