Day32-07|13.3.2 业务逻辑层工作流设计:让复杂业务过程可建模、可执行、可追踪
Day32-07|13.3.2 业务逻辑层工作流设计:让复杂业务过程可建模、可执行、可追踪
对应教材:《系统架构设计师教程(第2版)》第13章“层次式架构设计理论与实践”13.3“中间层架构设计”中的 13.3.2“业务逻辑层工作流设计”。本文面向软考高级系统架构设计师,系统学习工作流建模、流程引擎、状态机、任务分派、规则决策、事务补偿、版本和运行治理。
一、教材定位与学习目标
现实业务往往不是一次请求一次响应,而是由多个角色、多个系统和多个时间阶段共同完成。例如贷款审批需要提交资料、资格校验、风险评估、人工审核、合同签署和放款;采购流程涉及申请、预算、审批、下单、收货和结算;理赔流程涉及报案、材料收集、核损、审核、赔付和归档。流程中的步骤可能顺序执行、并行执行、条件分支、循环补充或等待外部事件。
如果这些流程全部写在一个巨大的业务方法中,代码很快会出现大量条件分支,流程变化需要频繁发布,运行状态难以查询,异常也没有统一恢复机制。业务逻辑层工作流设计的目标,是把业务过程中的活动、角色、状态、规则、输入输出和转移关系显式表示,并通过流程服务、状态机或流程引擎执行和管理。
工作流设计不是把业务规则全部交给流程引擎,也不是画一张流程图就完成架构。架构师必须划分流程控制、领域规则、人工任务、外部调用和数据一致性的职责,确保流程可执行、可恢复、可审计并能随着业务变化演进。
学习目标:
- 理解业务流程、工作流、状态机和业务规则之间的关系。
- 掌握顺序、并行、分支、循环、事件等待和人工任务建模。
- 设计流程引擎或工作流服务的职责边界与运行架构。
- 处理长事务、超时、失败、补偿、幂等、并发和流程版本。
- 能够结合案例题和论文说明工作流架构的设计与落地。
二、工作流的基本概念
1. 流程实例
流程定义描述一种业务过程的模板,流程实例则是某一次真实业务执行的记录。比如“采购审批流程”是定义,采购单PO2026001对应一个流程实例。实例要保存当前节点、业务标识、参与者、输入、状态、版本和历史轨迹,不能只依赖当前页面或内存变量。
2. 活动与任务
活动是流程中的业务步骤,可以是自动服务任务、人工任务、脚本任务、子流程或等待事件。自动服务任务调用应用服务或外部系统,人工任务需要分配给角色或具体人员,等待事件则等待消息、时间或外部状态。每类任务的超时和失败处理不同,应在模型中明确。
3. 网关与转移
网关用于表达条件分支、并行拆分、汇聚和选择路径。条件不能只写成模糊的“风险高则审核”,应说明输入数据、规则版本和决策结果。并行流程要定义汇聚条件,避免一个分支失败后主流程永远等待。
4. 流程状态
流程状态描述实例当前生命周期,如草稿、执行中、挂起、失败、人工处理、完成和取消。任务状态和流程状态要区分:某个短信通知失败,不一定意味着整个订单流程失败;某个审批任务完成,也不一定代表业务已最终完成。
5. 事件与消息
事件可以触发流程启动、推进或分支。例如付款成功事件推进订单,材料上传事件解除等待,定时器事件触发超时处理。事件要有唯一标识、来源、发生时间、业务关联和版本,并支持重复投递和重放治理。
三、工作流与状态机、业务规则的关系
1. 工作流描述过程
工作流重点描述活动如何连接、由谁执行、在什么条件下转移以及何时完成。它适合回答“先做什么、再做什么、谁来做、何时等待”。
2. 状态机描述生命周期
状态机重点描述业务对象或流程实例允许的状态和状态转移。订单从待支付到已支付、已发货和已完成就是典型生命周期。状态机可以嵌入工作流,也可以独立保护领域对象的不变量。
3. 规则引擎描述决策
规则引擎负责根据事实和规则产生决策,例如审批级别、赔付额度、优惠资格和风险等级。规则的输入、输出、优先级、版本和解释信息应独立治理。流程决定何时请求决策,领域或规则服务决定业务结果。
| 对象 | 主要回答 | 典型职责 |
|---|---|---|
| 工作流 | 过程如何推进 | 活动、角色、分支、等待、汇聚 |
| 状态机 | 当前处于什么状态 | 状态、转移、合法性、不变量 |
| 规则服务 | 应做出什么决策 | 条件、算法、优先级、版本 |
| 业务服务 | 如何完成业务动作 | 用例编排、事务、领域对象协作 |
混淆这些对象会导致流程引擎承载过多业务规则,或者业务代码中散落大量流程控制。合理设计应让它们通过明确契约协作。
四、工作流建模方法
1. 识别流程边界
先确定流程开始事件、结束条件、参与角色、外部系统和业务目标。不要把所有后台操作都放进一个流程,流程边界过大将导致状态复杂、恢复困难;边界过小又无法表达端到端业务价值。
2. 列出业务活动
把业务过程拆成可识别的活动,说明每项活动的输入、输出、责任人、前置条件、后置条件和失败方式。活动的粒度要能够独立执行、重试、审计或人工处理。
3. 描述分支和并行
分支应基于业务事实或规则结果,不应根据页面按钮随意决定。并行活动要明确是否全部完成、任意完成、按比例完成或允许超时后继续。汇聚条件不明确是工作流“卡死”的常见原因。
4. 识别等待点
等待外部回调、人工操作、定时窗口和资源可用都属于等待点。等待点需要持久化流程状态,不能占用线程或数据库长事务。每个等待点还要设计超时、取消和恢复策略。
5. 定义异常路径
正常流程只是工作流的一部分。必须补充输入错误、权限不足、服务不可用、业务拒绝、重复事件、超时、人工退回和不可恢复错误等路径,并说明用户和运维如何处理。
五、流程引擎的逻辑架构
1. 流程定义管理
负责创建、校验、发布、版本和下线流程定义。发布前要检查节点、条件、角色、服务引用和数据映射。流程定义与实例版本绑定,不能让正在运行的实例随意切换到新定义。
2. 流程运行时
负责创建实例、推进节点、保存状态、执行条件、调度任务、处理事件和完成流程。运行时必须保证关键状态变化的一致性,并能够在重启后恢复。流程引擎不能只依赖内存状态。
3. 任务管理
负责人工任务的创建、分派、认领、转交、委托、完成、退回和超时。任务分派可以按角色、组织、资源归属和业务规则确定。要防止任务被错误领取或无人处理,提供待办、催办、升级和转派机制。
4. 规则与表达式执行
流程需要判断条件和调用决策服务。表达式应使用受控语法,限制访问对象和函数,避免任意代码执行。复杂规则应由规则服务管理,流程引擎只接收决策结果。
5. 服务任务执行器
执行器调用应用服务、消息服务和外部系统。它要处理超时、重试、幂等、熔断、错误映射和结果回写。外部调用不能依赖流程引擎的长事务,失败后应通过状态和补偿恢复。
6. 事件与定时器
事件总线或消息队列负责接收外部事件,定时器负责超时、提醒和定期任务。事件处理必须去重,定时器重复触发也不能产生重复业务。调度数据要持久化,节点重启后可以恢复待执行任务。
7. 监控与审计
监控流程实例数量、各节点耗时、待办积压、失败率、超时数量、消息延迟和补偿情况。审计记录定义版本、操作者、状态变化、规则结果、外部调用和异常处理,满足追责和问题排查。
六、工作流中的一致性与可靠性
1. 不使用长数据库事务包住整个流程
跨人工步骤和外部系统的流程可能持续数小时或数天,不能保持数据库长事务。应在每个活动完成后保存状态和业务事实,必要时发布事件,下一步根据事实继续。
2. 幂等执行
任务重试、消息重复和引擎恢复都可能再次执行同一活动。每个自动任务要有流程实例ID、节点ID、执行次数和业务幂等键;执行前检查已有结果,执行后记录结果。对于外部系统,优先使用对方提供的业务单号或幂等接口。
3. 补偿而非盲目回滚
已经调用外部系统的操作通常无法通过本地事务回滚。应设计补偿动作,例如取消预留、冲正支付、撤销发运或生成人工处理任务。补偿本身也要幂等、可审计并有失败告警。
4. 超时与重试
不同节点需要不同超时策略。临时网络错误可以指数退避重试,业务拒绝不应重试,持续失败应熔断并进入人工或死信处理。流程超时要区分提醒、升级、自动取消和转人工。
5. 并发与锁定
同一业务对象可能被多个流程或人工任务同时修改。可以使用版本号、乐观锁、业务锁或串行化队列控制冲突。工作流引擎的实例锁不能替代领域对象的并发控制。
七、流程版本和变更治理
1. 新实例使用新版本
新发布流程定义通常服务于新实例,旧实例继续使用原版本,以保证历史语义稳定。若必须迁移运行中的实例,需要定义节点映射、数据兼容、人工确认和回退策略。
2. 规则与流程分别版本化
同一流程可能使用不同产品规则、政策规则或组织规则。流程版本和规则版本应分别记录,结果才能复现和审计。历史审批不能因为新规则发布而被重新解释。
3. 配置发布流程
流程设计、测试、审核、发布和运维权限要分离。上线前进行路径覆盖、角色矩阵、异常、超时、重复事件和性能测试;发布采用灰度、开关和快速回滚。
4. 流程债务治理
流程越改越复杂时,要识别重复节点、无效分支、长期挂起实例和过时规则。流程重构应先分析运行数据,再通过新版本逐步迁移,不能直接删除仍在运行的旧节点。
八、案例分析:银行贷款审批工作流
某银行贷款申请流程包括客户提交资料、系统初审、风险评分、人工审核、合同签署、放款和贷后提醒。原系统将所有步骤写在一个服务方法中,人工审核状态通过数据库字段表示,外部征信和放款接口失败后只能人工查表,流程版本变更还会影响历史申请。
1. 流程模型
以“贷款申请提交”作为启动事件,依次经过资料校验、征信查询和风险评分。根据规则结果进入自动通过、人工审核或拒绝分支;人工审核可以退回补充资料;合同签署完成后调用放款服务;放款成功后发布贷后管理事件。每个步骤具有明确状态、责任和超时。
2. 组件划分
流程服务负责实例和节点推进,资料服务负责材料校验,风险规则服务负责评分与决策,贷款领域服务负责申请状态和核心不变量,征信与放款适配器负责外部协议,任务中心负责人工待办,消息和审计平台负责通知与追踪。
3. 可靠性设计
征信查询使用请求编号和有限重试,超时后进入待补偿状态;放款使用贷款合同号作为幂等键,超时后查询最终状态;人工审核完成前不保持数据库长事务;资料补充通过事件唤醒挂起实例;流程重启后从持久化节点状态恢复。
4. 版本治理
流程定义、风险规则和合同模板分别版本化。新申请采用新版本,历史申请绑定创建时的流程和规则版本。若监管要求调整尚未放款的申请,通过受控迁移将特定实例从旧节点映射到新节点,并保留迁移审计。
5. 指标
使用自动审批比例、人工任务平均等待时间、流程超时率、外部调用成功率、重复放款数、补偿完成率、版本迁移失败数和客户申请完成时间评价效果。
九、综合知识练习与详细答案
练习一:单项选择
长时间运行的业务流程最适合采用( )保存进度。
A. 线程阻塞等待 B. 数据库长事务 C. 持久化流程实例和状态 D. 浏览器隐藏字段
答案:C。长流程应持久化实例和状态,不能占用线程、保持长事务或信任客户端字段。
练习二:多项选择
工作流服务设计通常需要考虑( )。
A. 流程版本 B. 人工任务超时 C. 自动任务幂等 D. 异常补偿 E. 只设计正常路径
答案:A、B、C、D。异常路径是工作流设计的重要组成部分。
练习三:案例题
某流程引擎在节点执行失败后自动重试,结果同一笔业务被重复扣款。请分析原因并提出改进措施。
参考答案:原因是自动任务没有业务幂等控制,且引擎无法区分“请求未发送”“请求已发送但响应丢失”和“业务已拒绝”;流程重试直接再次调用扣款接口,可能造成重复副作用。改进时应为扣款定义稳定业务幂等键,调用前记录执行状态,调用超时后先通过扣款单号查询结果,再决定重试;优先使用支付方的幂等接口和查询接口;将网络错误、业务拒绝和未知状态分别处理;对已扣款但流程未推进的情况采用状态补偿和对账;设置有限重试、退避、熔断和人工处理;记录请求ID、流程实例、节点版本和外部交易号,保证可审计。
十、案例题答题模板
遇到工作流、审批、流程引擎和长事务类题目,可以按以下顺序作答:
- 明确业务目标、启动事件、参与角色、结束条件和流程边界。
- 把流程拆成活动、任务、状态、分支、并行、等待和异常路径。
- 区分流程控制、领域规则、状态机、人工任务和外部适配器的职责。
- 设计持久化实例、节点状态、事件、定时器和运行恢复机制。
- 处理幂等、超时、重试、并发、补偿和人工介入。
- 设计流程、规则、模板和数据的版本、灰度、迁移与回滚。
- 用流程时效、积压、失败、补偿、自动化比例和业务完成率验证效果。
十一、论文写作素材
开头素材
“原有贷款审批系统将多个自动步骤和人工环节硬编码在单一业务方法中,导致流程变更困难、状态不可追踪、外部调用失败后无法自动恢复。为提高流程的可维护性和可靠性,我参与设计了业务工作流架构,将流程定义、运行时、人工任务、规则服务、外部适配器和审计监控进行职责分离。”
正文素材
可以重点写四点:第一,如何围绕业务目标识别流程边界,建立活动、状态、分支、并行和等待模型;第二,如何避免长事务,通过持久化实例、事件和状态机支撑长流程;第三,如何处理自动任务的幂等、超时、重试、补偿和外部接口未知状态;第四,如何进行流程、规则和数据版本治理,保证历史实例可追溯,并通过人工任务、灰度和运行指标保障落地。
结尾素材
“实践表明,工作流架构的价值不只是让业务流程图能够运行,更在于让过程状态、责任、异常和演进都可见、可控、可恢复。通过流程与领域规则分离、持久化状态、幂等补偿和版本治理,企业可以在快速调整业务流程的同时保持核心交易的正确性和可审计性。”
十二、今日复盘
本节核心结论是:工作流描述业务过程,状态机保护生命周期,规则服务产生决策,业务服务完成业务动作;长流程必须持久化、可恢复,并为重复、超时和补偿设计明确路径。
请回答:
- 流程定义和流程实例有什么区别?
- 工作流、状态机和规则引擎分别解决什么问题?
- 为什么长流程不能使用数据库长事务?
- 自动任务如何处理超时和未知结果?
- 人工任务需要哪些分派、超时和审计机制?
- 为什么流程版本、规则版本和实例状态必须关联?
请以贷款、采购、理赔或报销为例,画出“流程定义—流程实例—任务—规则—领域服务—外部适配器—事件/定时器”的关系,标注事务边界、幂等键、补偿、人工介入和审计位置。完成后,你就掌握了 13.3.2 在综合知识、案例分析和论文写作中的核心能力。