首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >使用Saga模式构建弹性航班预订工作流

使用Saga模式构建弹性航班预订工作流

原创
作者头像
qife122
发布2025-08-17 23:27:25
发布2025-08-17 23:27:25
950
举报

现代航班预订和支付系统由跨越多个服务的众多步骤组成。例如,航空公司预订可能涉及一个服务来预订座位,另一个来处理支付,第三个来签发机票(确认座位)。所有这些步骤都必须成功完成预订;如果任何步骤失败,则应撤销先前步骤的影响以避免不一致。在单体系统中,单个ACID事务可能处理这个问题。但在分布式微服务架构中,没有单一事务可以轻松跨越系统和座位的支付。正如一篇文章所指出的,在航班预订场景中,座位预订微服务无法获取支付数据库(通常是外部服务)的锁,因此需要采用不同的方法来管理事务——一种拥抱松耦合和最终一致性的方法。这就是状态机和Saga模式发挥作用的地方。

状态机将流程建模为一系列离散状态和响应事件的转换。我们可以定义与预订每个阶段相对应的状态(座位选择、票价保留、支付处理、机票签发等)以及由“支付成功”或“座位保留过期”等事件触发的转换。例如,旅行预订流程可能有诸如“预订航班”、“预订酒店”、“预订汽车”、“确认”和“错误”等状态。事件然后驱动这些状态之间的转换:例如,“航班预订”事件从“预订航班”移动到下一个状态,而“航班预订失败”事件则转换到“错误”状态。基于时间的事件如“票价保留超时”也是模型的一部分。通过列举所有成功和失败事件(包括超时),工程师可以明确捕获系统在每个步骤应如何反应,确保没有结果被忽略。

这种状态机方法比临时脚本或流程图更正式和严格。每个预订状态(例如“座位保留”、“待支付”、“已出票”)代表工作流中的一个明确阶段,转换定义了当支付授权失败或保留期失效时应发生的情况。状态机作为预订流程逻辑的单一真相来源,这对于理解和维护复杂的旅行系统至关重要。它提供了所有可能路径的可视化文档,使团队更容易推理和演化工作流。

使用Saga状态机编排多步骤事务

由于航班预订跨越多个服务且不能依赖传统的分布式提交,系统采用Saga模式——本质上是一个具有补偿操作的长运行事务的状态机。Saga是一系列本地事务,每个事务提交自己的数据。如果一个步骤失败,Saga执行补偿事务以撤销先前步骤的影响,确保系统返回到一致状态。在我们的上下文中,如果在座位保留后支付失败,补偿步骤将释放该座位保留。不是通过锁定资源来实现全有或全无的一致性,而是通过在失败时显式撤销已完成的步骤来实现。这种方法与分布式系统中可靠性的BASE哲学(“基本可用、软状态、最终一致”)一致。

为了实现Saga,有两种主要策略:编排(choreography),其中服务相互响应事件;和编配(orchestration),其中中央控制器驱动流程。对于复杂的工作流,编配通常更容易观察和管理。在编配的Saga中,专用工作流引擎或状态机驱动预订流程,按顺序调用每个服务并集中处理错误。该编配器跟踪事务当前所处的步骤以及下一步需要发生什么或需要回滚的内容。实际上,编配器本身体现了一个状态机:它保存关于当前步骤的状态,等待事件(响应或超时),并相应地转换工作流。

Google Cloud Workflows(GCP Workflows)是为这种编配构建的平台的一个例子。它允许工程师将工作流定义为一系列具有给定操作、条件和转换的步骤——本质上为其流程定义一个云托管的状态机。在底层,“您将状态机定义为描述您的工作流的一系列步骤、它们的关系以及它们的输入和输出。”这个概念,正如AWS Step Functions类似地描述的,允许您通过声明性状态机协调分布式服务。GCP Workflows是无服务器和有状态的,这意味着它将在步骤之间甚至长时间等待中保持执行状态。Google的文档强调,有状态工作流使得端到端可视化和监控复杂的服务交互变得容易。与每个微服务处理流程的一部分(状态在请求或消息中传递)不同,工作流作为协调预订事务所有部分的中央大脑。

GCP Workflows:实践中的可靠性、重试和超时

使用像GCP Workflows这样的平台进行航班预订的一个关键优势是内置的可靠性和故障处理功能。工作流可以“通过默认或自定义的重试逻辑和错误处理来控制故障,即使其他系统失败”,并且它将每个步骤检查点到持久存储。检查点意味着如果编配器本身崩溃或流程中断,它可以从最后一个已知状态恢复而不必从头开始——这对于长时间运行的预订至关重要。事实上,工作流自动跨区域复制状态,并将在中断后继续执行,这大大提高了弹性。

重试逻辑内置于工作流定义中。与其在每个服务或客户端中编写自定义重试循环,编配器可以为任何步骤声明重试策略。例如,如果支付服务或外部API调用返回暂时性错误(如网络超时或503服务不可用),工作流可以自动重试该步骤几次,然后才认为它是永久性失败。这提高了可靠性,而不会使单个微服务复杂化。Google Cloud Workflows为这些try/retry块提供了简单的语法,允许在所有步骤中保持一致的重试策略,而无需修改服务代码。因此,信用卡授权或座位图API中的暂时性故障不会立即中止整个预订——状态机将暂停并按配置重试。

如果一个步骤以不可恢复的方式失败,工作流可以触发补偿步骤来回滚。GCP Workflows通过将错误路由到特殊的处理程序步骤来支持Saga风格的补偿。正如Google的倡导者所描述的,“这是Saga模式,其中链中的失败调用触发链中的补偿调用。”例如,如果座位分配步骤成功,但随后的票价支付步骤不可恢复地失败(例如支付被拒绝且没有替代方案),工作流的异常处理程序可能会调用“取消座位”操作以释放先前保留的座位。使用Workflows的YAML语法,可以为每个需要回滚的步骤定义一个except路径。通过重试和Saga机制的结合,“暂时性故障由重试策略处理,不可恢复的错误由补偿步骤处理”,从而产生一个对现实世界问题更具弹性的工作流。这种混合自动重试暂时性问题和编配回滚永久性故障的能力是有状态工作流引擎的标志。

超时和长延迟是有状态工作流表现出色的另一个领域。在航班预订中,一个常见的场景是票价保留:系统为客户的行程和票价保留一段时间(例如24小时)等待支付。使用无状态服务实现这一点可能很棘手——您可能需要一个cron作业或带有延迟的消息来触发保留过期。然而,在工作流中,等待是一等公民。GCP Workflows可以简单地等待指定的持续时间或直到事件发生,然后转换状态。该平台支持长达一年的等待,远远超过票价保留的需求。例如,在座位保留后,工作流可以进入一个“保留中”状态,该状态等待(异步,不消耗资源)支付确认事件或24小时计时器到期。如果计时器首先触发,工作流知道保留已过期,并可以调用服务释放保留。这种方法比构建自定义调度器和状态存储来跟踪保留要干净得多。实际上,最终一致性中的一个挑战是检测步骤何时未完成(例如用户从未支付)——状态机通过建模超时转换使这一点变得明确。

让我们考虑几个匿名的真实示例以及状态机编配如何处理它们:

部分座位分配失败:旅行者选择多个航班行程中的座位。座位选择服务确认一条航段,但在另一条航段上座位被另一位客户同时占用,导致该分配失败。在有状态工作流中,此失败将触发转换到特定于座位选择的错误处理状态。工作流可以决定在受影响的航段上重试座位分配(可能自动选择不同的座位),或执行补偿操作以取消第一条航段上已预订的座位,确保预订不会半途而废。相比之下,在无状态方法中,跨服务协调此回滚将很麻烦。使用Saga状态机,逻辑是集中的:在“座位分配失败”事件上,调用保持行程一致所需的撤销步骤。这种补偿事务模式的使用干净地“撤销了步骤执行的工作”,当多步骤操作无法完成时。

票价保留超时:许多航空公司允许客户保留预订有限时间。在工作流中,一旦预订被保留,状态机进入“等待支付”状态。编配引擎可以休眠直到支付截止日期,或者在收到支付时提前唤醒。如果截止日期过去而没有支付事件,状态机自动触发过期路径:它可能会向客户发送通知并调用预订服务取消临时预订。这种基于时间的转换可靠地发生,因为编配器正在跟踪经过的时间(能够本地等待数小时或数天)。没有有状态工作流,实现这一点将需要外部调度器或持续运行的进程。然而,GCP Workflows专为这种长时间运行的多步骤业务事务设计,能够等待事件或超时并在定义的状态逻辑内处理它们。

支付处理和重试:支付交易偶尔由于网络问题、处理器中断或资金不足而失败。一个健壮的预订系统应在放弃之前尝试重试支付或尝试替代方法。在状态机中,“支付”状态可以在暂时性失败事件上有转换,循环回并重试收费(可能在短暂延迟或路由到备用支付网关之后)。GCP Workflows通过允许为支付步骤声明重试策略使这一点变得简单——例如,在超时或5xx错误上重试最多3次。在这些重试期间,整体预订状态保持不变(座位保持保留)。如果所有重试失败,状态机转换到“支付失败”路径。此时,补偿逻辑可能会取消预订保留并通知用户。关键的是,工作流编配器记录每次尝试和结果,因此操作员可以全面了解发生了什么。没有有状态编配器,这些重试尝试及其协调将必须手动编码,并且很容易变得不一致。通过将其合并到一个工作流中,流程既一致又更容易调整(例如,更改重试计数或添加备用支付步骤是对工作流定义的一次性更改)。

分布式旅行系统中有状态编配的好处

使用基于状态机的工作流(如GCP Workflows)进行航班预订和支付在弹性、可观察性和可维护性方面带来了显著的好处:

提高弹性和一致性:Saga编配器确保所有步骤成功完成或运行补偿操作以撤销部分工作。这防止了诸如座位售出但未支付,或支付捕获但未签发机票等问题。工作流的内置重试优雅地处理间歇性故障,而其补偿逻辑处理业务规则失败。即使没有传统事务,整体流程也变得“基本可用”和“最终一致”。此外,由于工作流引擎在每个步骤后检查点状态,预订中间的崩溃或中断不会从头重新启动流程——它会在服务恢复时从最后一个已知状态恢复。这种容错(包括状态的跨区域复制)大大提高了可能跨越数分钟或数小时的长时间运行预订的可靠性。

增强的可观察性和监控:有状态工作流提供每个预订事务的单一连贯时间线。像GCP Workflows这样的工具为每个步骤提供开箱即用的日志记录和监控,为工程师和支持团队提供关于延迟或故障发生位置的清晰洞察。由于编配是集中定义的(通常在YAML/JSON中),平台可以可视化工作流并跟踪通过状态的进度。Google指出,工作流是自文档化的,每个步骤都有名称且可观察,使得理解业务流程变得容易。相比之下,纯粹的事件驱动或无状态实现会将这种逻辑分散在服务和队列中,需要复杂的日志关联来找出事务的状态。使用状态机方法,可以查询编配器以获取预订的当前状态(例如,“等待支付”或“错误——支付被拒绝”)并对其准确性有信心。这种集中式上下文大大简化了调试和跟踪诸如卡住的预订或特定步骤中的系统性减速等问题。

更高的可维护性和可扩展性:将航班预订逻辑封装在高级工作流定义中使得系统随着时间的推移更容易更改。添加新步骤(例如支付后的额外欺诈检查或发送确认电子邮件)是更新工作流规范的问题,而不是触及多个服务。工作流作为业务逻辑的单一真相来源,减少了不同服务误解流程的风险。由于状态机是正式和明确的,它们也作为业务流程的实时文档——新工程师可以阅读状态转换并比阅读几个微服务中的分散代码更容易理解端到端流程。这在旅行行业尤其有价值,其中业务规则(如取消政策或保留持续时间)经常变化;定义良好的状态机可以在一个地方更新并立即反映新规则。作为额外的好处,状态图的清晰性通常会暴露在非正式实现中可能被忽略的边缘情况(如部分座位分配失败)。总的来说,团队发现当状态和转换由专用引擎跟踪时,维护复杂的工作流更容易,而不是隐含在无状态API的交互中。

微服务专注于核心功能:通过将编配逻辑卸载到工作流引擎,每个微服务(库存、支付、出票等)可以保持更简单和无状态。它们只需执行其本地事务(保留座位、收费等)并报告成功或失败。它们不需要了解整体预订流程或处理多步骤依赖关系。这减少了服务之间的耦合并允许独立开发。状态机编配器协调这些调用和决策,将复杂的业务事务逻辑集中在一个地方。这种分离通常导致更干净的服务代码和更容易的测试,因为工作流可以模拟各种场景(包括故障)以确保Saga逻辑正确。

总之,由状态机驱动的有状态工作流已成为现代航班预订和支付系统背后不可或缺的架构模式。它们提供了一种健壮的方式来管理构成预订的座位选择、保留和支付的Saga。通过利用像GCP Workflows这样的平台作为编配引擎,航空公司和旅行平台实现了具有重试和补偿的强大可靠性、更好地了解每个事务以及适应业务流程的灵活性。与纯粹的无状态微服务调用相比,有状态工作流可以优雅地处理长时间运行的交互——从保留数小时的座位到第二次尝试成功的支付——同时保持系统状态一致。这导致了一个更具弹性、可观察和可维护的旅行预订系统,确保旅行者的预订即使在发生意外情况时也能可靠地处理。幕后的状态机悄悄地确保每次购买机票的旅程都达到正确的结论,或干净地回滚,就像经验丰富的指挥家将复杂的服务交响乐编配成和谐的结果。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 使用Saga状态机编排多步骤事务
  • GCP Workflows:实践中的可靠性、重试和超时
  • 分布式旅行系统中有状态编配的好处
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档