我在工作中遇到架构问题, 有一些记录进入 SNS FIFO 主题,每条进入的记录都需要由 3 个不同的模块按顺序处理。 为了简单起见,我们假设模块是 Lambda A、B、C。
严格要求
最明显的方法是在 Lambda A、B、C 之间使用 SQS FIFO 进行编排
Record -> SNS FIFO -> SQS FIFO -> Lambda A -> SQS FIFO -> Lambda B -> SQS FIFO -> Lambda C
这将使调试单个记录的故障点变得非常困难,不是不可能,但有点耗时。
我想到的另一种方法是,既然这 3 个 Lambda 需要按顺序执行并且是相关的,为什么不使用编排而不是使用Step Functions (SF)。
Record -> SNS FIFO -> SQS FIFO -> SF Invoke Lambda -> SF (Lambda A -> Lambda B -> Lambda C)
这里的问题是 SF Invoke Lambda 将触发并忘记组 ID 中每条消息的 SF,这将打破第二个严格要求。
解决这个问题的方法是在为 SF Invoke Lambda 中的下一条消息调用 SF 的新执行之前检查先前的 SF 是否已完成执行。这将通过检查数据库中每个执行的 process_state 来完成,Lambda C 将负责将其更新为“成功/失败”状态。
Record -> SNS FIFO -> SQS FIFO -> SF Invoke Lambda -> SF (Lambda A -> Lambda B -> Lambda C -> Update DB)
-> SF Invoke Lambda -> Check DB for process_state -> SF (Lambda A -> Lambda B -> Lambda C -> Update DB)
问题:
a.使用消息中的唯一值(如果有的话)跟踪该消息,或者在 DynamoDB 或 Redis 或任何其他数据库中创建消息的哈希值。在 Lambda(A) 中执行此操作
b.在 Lambda A、B 和 C 中执行您计划执行的任何处理
c.在退出 Lambda(C) 之前,更新数据库中该特定消息的状态(Dynamo、Redis 或您使用的任何数据库)。
d。在轮询来自 Lambda(A) 的下一条消息之前,请通过检查(Dynamo、Redis 或您使用的任何数据库)存储当前处理项目的引用的位置来检查是否有任何仍在处理的内容。如果现有消息尚未完成,则跳过执行。
如果您愿意,还可以将每个 Lambda 的状态存储在数据库中,如下所示
[消息、Lambda A 结果、Lambda B 结果、Lambda C 结果、最终状态]。它也会让调试变得更容易