Day34-02|15.1.2 业务流程与 BPEL:让多个服务协同完成企业流程

一、教材定位与学习目标

15.1.2“业务流程与 BPEL”讨论 SOA 中一个非常重要的问题:服务已经被拆分并封装后,如何让多个服务按照业务顺序、条件和异常规则协同完成一个完整流程。企业业务通常不是一次接口调用,而是包含校验、审批、库存、支付、发货、通知和人工处理的长流程。流程设计决定了服务组合是否可理解、可监控、可恢复。

BPEL(Business Process Execution Language,业务流程执行语言)是一类用于描述和执行 Web 服务业务流程的语言。考试中不一定要求记住全部语法,更重视流程编排、伙伴服务、变量、顺序、并行、条件、异常、补偿和长事务等概念。本篇以订单履约为例,说明如何把服务组合成可执行流程。

学习完成后,应能够:

  1. 解释业务流程、服务编排和 BPEL 的关系。
  2. 区分编排与编舞,并分析各自适用场景。
  3. 设计顺序、并行、条件、循环和异步回调等流程结构。
  4. 处理跨服务长事务、异常、超时、补偿和人工干预。
  5. 用案例题语言说明流程引擎的价值、风险和治理措施。

二、为什么需要业务流程层

单个服务只负责一个相对明确的业务能力,而企业用例往往需要多个服务共同完成。例如“采购申请”要经过预算检查、审批、供应商询价、合同生成和付款;“网上购物”要完成订单创建、库存预占、支付、履约和通知。如果把整个流程逻辑散落在多个服务和页面中,流程变化会带来大范围修改,失败时也没有统一的状态和补偿。

业务流程层把跨服务的协作顺序和规则显式表达出来,使参与服务保持相对自治,同时让流程能够被监控、暂停、恢复和重试。它不是把所有业务逻辑集中到一个巨大流程服务中,服务自身的核心规则仍应由服务负责;流程层负责跨边界协调。

三、业务流程的基本组成

一个可执行业务流程通常包括:

组成 含义 例子
活动 流程中的一个步骤 创建订单、预占库存
参与者 提供能力的服务或人工角色 库存服务、审批人
数据变量 在步骤间传递的业务数据 订单号、金额、状态
控制流 步骤之间的顺序和条件 先校验,再支付
消息 服务间异步通信 支付完成事件
异常处理 失败、超时和错误分支 释放库存、人工审核
补偿 对已完成动作进行业务撤销 取消预占、退款
监控状态 流程实例的运行信息 处理中、失败、完成

流程不仅要描述正常路径,还要描述失败路径。考试答题时,如果只写“调用订单、库存和支付服务”,没有写支付超时、库存释放、重复回调和人工补偿,方案是不完整的。

四、流程编排与流程编舞

4.1 编排

编排由一个中心流程协调者负责决定调用顺序、条件、超时和补偿。参与服务提供接口或事件,流程引擎维护流程实例状态。

流程协调者
   ├── 调用订单服务
   ├── 调用库存服务
   ├── 等待支付事件
   └── 通知履约与消息服务

优点是流程清晰、易于查看全局状态和统一异常处理,适合审批、订单履约和跨系统协同。缺点是协调者需要维护流程模型,可能成为性能瓶颈或集中式复杂点,服务自治也可能受到影响。

4.2 编舞

编舞没有一个中心协调者,各服务根据事件和契约自主反应。例如订单创建事件触发库存服务,库存预占事件触发支付服务,支付完成事件触发履约服务。优点是松耦合和扩展灵活,缺点是全局流程难以理解,排障、版本和一致性治理更复杂。

编排适合流程规则集中、步骤顺序重要的场景;编舞适合参与方自治、事件驱动和后续消费者较多的场景。二者可以组合:核心流程由编排控制,通知、积分和分析由事件编舞完成。

五、BPEL 的基本角色

BPEL 用于描述由 Web 服务参与的业务流程,通常涉及流程定义、伙伴链接、消息变量、活动、相关集、异常和补偿等概念。

5.1 伙伴服务

流程需要与多个外部或内部服务交互,这些服务可以看作伙伴。伙伴关系定义流程如何调用服务、服务如何回调流程以及通信契约。伙伴接口不应把服务内部实现暴露给流程。

5.2 流程变量

变量保存订单号、客户、金额、库存结果、支付结果和错误信息等。变量应控制范围和敏感级别,避免在流程实例中长期保存不必要的个人信息和支付数据。流程持久化时,敏感字段应加密或脱敏。

5.3 活动结构

常见结构包括顺序执行、并行执行、条件分支、循环、接收消息、调用服务、回复消息、等待和作用域。复杂流程应拆成有意义的子流程,避免一个流程定义包含过多细节而难以维护。

5.4 相关集

异步回调到达时,流程引擎需要知道该消息属于哪个流程实例。可以使用订单号、申请号或业务关联键建立相关关系。关联键必须稳定、唯一且不可轻易被用户篡改,回调验签和权限校验不能省略。

六、顺序、并行和条件控制

6.1 顺序

顺序适合有依赖的步骤,例如先校验订单,再预占库存,再创建支付。顺序链过长会增加总延迟和故障传播,应识别可以并行的独立动作。

6.2 并行

订单创建后,发送营销消息、更新搜索索引和记录分析事件可以并行执行,不必相互等待。并行分支需要定义汇聚条件:全部完成、任意完成、超时继续还是失败即终止。并行会增加资源和消息量,应考虑下游容量。

6.3 条件与循环

根据库存、会员等级、支付方式或风险评估结果选择不同分支;对多个审批人或多个供应商进行循环处理。条件应基于版本化业务规则,不能把大量易变规则硬编码在流程模型中,否则每次活动调整都需要修改和发布流程。

七、长事务与补偿事务

7.1 为什么需要长事务

企业流程可能持续数分钟、数小时甚至数天,例如审批、支付等待、物流履约和退货。流程不能让一个数据库事务一直持有锁,也不能要求所有参与系统支持统一分布式事务。因此,需要把流程拆为多个本地事务,通过状态和消息推进。

7.2 补偿而不是回滚

分布式流程中,已完成的动作往往不能物理回滚,只能执行业务补偿。例如库存预占后支付失败,调用释放库存;支付成功后履约失败,进入退款或人工处理;已发送的短信无法撤销,只能发送更正通知。补偿动作也可能失败,需要重试、人工处理和审计。

7.3 Saga 思想

可以把长流程拆成一系列本地事务,每个事务有对应的补偿动作。流程成功时依次推进,失败时按照业务规则执行逆向补偿或进入人工处理。补偿不一定严格按原顺序,也不一定能恢复到完全初始状态,因此要明确最终业务目标和可接受异常。

八、异常、超时与重试

流程中要区分技术异常、业务异常、超时和取消。技术异常可以有限重试;业务拒绝应进入业务分支;超时要查询真实状态,不能直接判断失败;用户取消要检查当前步骤是否允许取消。

流程引擎和服务客户端都可能重试,必须统一责任,设置整体截止时间和退避策略。每个活动要有幂等键和处理记录,异步回调要验签和去重。流程实例恢复时,应知道上一步是否已经成功,不能因为引擎重启而无条件重复执行副作用。

九、流程持久化与恢复

长流程必须保存实例状态、当前活动、变量、消息相关键、版本和错误信息。引擎重启或节点故障后,可以从持久化状态恢复。流程实例需要关联业务单号,支持查询、暂停、人工重试、跳过或补偿,但这些管理操作必须有权限和审计。

流程定义升级要区分新旧实例。已经运行的实例可能继续使用旧版本,新创建实例使用新版本;如果必须迁移,应定义变量兼容和活动映射。不能直接覆盖流程定义,导致历史实例无法恢复。

十、BPEL 与 Web 服务集成

BPEL 传统上与 WSDL、SOAP、XML 和 Web Service 生态联系紧密。服务契约描述操作、消息和数据类型,流程通过标准接口调用伙伴服务。企业也可能使用 REST、消息和现代工作流平台实现同类思想。

考试中不要把 BPEL 等同于某个协议的语法题。重点应放在服务组合、契约、流程控制、异步回调、异常补偿和治理。BPEL 或流程引擎选择要考虑现有系统协议、流程复杂度、团队能力、性能、可视化、版本和供应商锁定。

十一、案例分析:供应链采购流程

某制造企业采购流程包括申请、预算校验、部门审批、供应商询价、合同生成、收货和付款。部分步骤需要人工等待,供应商接口不稳定,要求能够追踪每一笔采购并在失败时恢复。

可以由流程引擎编排:申请服务创建流程实例,预算服务同步校验,审批服务通过消息回调完成多级审批,询价服务并行调用多个供应商,选择结果后生成合同,收货事件触发验收,验收通过后付款。每个步骤都有超时、状态和关联号;供应商失败使用有限重试和备用供应商,审批超时转人工;合同和付款使用幂等;收货失败不直接回滚已完成审批,而是进入取消或补偿流程;流程实例和敏感变量持久化并审计。

采购流程的核心业务规则仍由预算、合同和付款服务负责,流程层只协调跨服务步骤。若审批和供应商询价都可以独立进行,可以并行;若付款必须等待验收,则保留顺序依赖。流程版本升级时,旧采购实例继续按旧版本完成,新实例使用新规则。

十二、课后练习

练习一:选择题

SOA 业务流程中,适合采用补偿而不是数据库回滚的情况是( )。

A. 同一个本地事务中的两条数据库更新

B. 已调用外部支付平台并收到成功结果后,后续履约失败

C. 尚未执行的本地方法

D. 变量尚未保存

答案:B。 外部支付通常不参与本地事务,无法通过数据库回滚撤销,需要退款或人工补偿。

练习二:简答题

请说明编排和编舞的主要区别。

参考答案: 编排由中心协调者管理流程顺序、条件、超时和补偿,整体流程清晰,适合规则集中和流程较复杂的业务;编舞由各服务根据事件和契约自主反应,没有统一协调者,耦合较低但全局追踪和治理更难。实际系统可以组合使用,核心步骤编排,通知和分析等后续动作采用事件编舞。

练习三:案例题

某订单流程调用库存、支付、物流和通知服务。支付已成功但物流创建失败,流程引擎重试后又重复创建订单。请分析并提出改进。

参考答案: 流程缺少活动级幂等和明确状态,重试时没有判断订单是否已经创建成功;支付和物流属于跨系统操作,不能依赖一个分布式数据库事务。应为订单创建、库存预占、支付和物流分别设置业务幂等键,保存请求和处理记录;流程持久化每一步状态,恢复时先查询真实状态再决定重试;物流失败时使用有限退避重试,超过上限切换备用渠道或进入人工处理,支付成功不能简单回滚;根据业务规则释放库存或退款,并通过状态机推进订单;通知异步发送并单独重试。所有回调验签、审计和对账,避免重复副作用。

十三、论文写作素材

本节适合用于“论 SOA 业务流程编排”“论企业长事务与补偿设计”或“论跨系统业务流程治理”。论文可以从流程透明、服务复用和异常恢复三个方面展开:用流程引擎协调服务,用消息和回调处理长等待,用状态机、幂等、补偿和审计保证可恢复。

论文中必须区分技术回滚和业务补偿。数据库事务回滚适合本地原子操作,跨服务流程需要补偿、对账和人工干预;流程引擎可以记录和恢复状态,但不能代替业务服务的授权、金额和库存规则。把这些边界写清楚,答案会更有深度。

十四、今日复盘清单

  • 我能否解释为什么需要业务流程层?
  • 我能否区分编排和编舞?
  • 我能否描述 BPEL 中伙伴服务、变量、活动和关联键的作用?
  • 我能否设计顺序、并行、条件、异步回调和长事务?
  • 我能否用补偿、幂等、重试、超时和审计处理跨服务失败?
  • 我能否说明流程版本升级和实例恢复的要求?

本节的核心结论是:SOA 业务流程通过编排或编舞把多个服务组合为完整业务能力,BPEL 及类似流程技术负责表达控制流、消息、变量、异常和补偿。真正可靠的流程必须面向长事务和部分失败设计,用持久化状态、幂等、有限重试、补偿、人工处理和审计形成可恢复闭环。