当前位置: 首页 > news >正文

别再乱写回退代码了!Activiti7流程驳回的两种正确姿势与性能对比

Activiti7流程驳回的深度实践:高并发场景下的两种优雅解决方案

在复杂的企业级工作流系统中,流程驳回(回退)是最常见但也最容易引发性能问题的操作之一。许多开发团队在面对驳回需求时,往往采用临时修改流程方向的方式实现,这在简单场景下或许可行,但在高并发、长流程的工单系统中,这种做法可能导致数据库锁竞争、历史数据混乱等一系列棘手问题。本文将深入剖析Activiti7中两种更安全、更高效的流程驳回实现方案,并通过压力测试数据对比它们的性能表现,帮助架构师和资深开发者做出合理的技术选型。

1. 传统动态改流向方案的隐患分析

动态修改节点流向是最直观的驳回实现方式,但这种方式在高并发系统中潜藏着诸多风险。让我们先看一个典型的实现代码:

public void backProcess(Task task) throws Exception { // 获取历史任务列表(按创建时间降序) List<HistoricTaskInstance> hisTaskList = historyService.createHistoricTaskInstanceQuery() .processInstanceId(processInstanceId) .orderByTaskCreateTime() .desc() .list(); // 获取当前和前一个任务节点 HistoricTaskInstance currentTask = hisTaskList.get(0); HistoricTaskInstance lastTask = hisTaskList.get(1); // 修改当前节点流向 FlowNode currentFlowNode = (FlowNode)bpmnModel.getMainProcess() .getFlowElement(currentActivity.getActivityId()); List<SequenceFlow> originalFlows = new ArrayList<>(currentFlowNode.getOutgoingFlows()); currentFlowNode.getOutgoingFlows().clear(); // 创建新流向 SequenceFlow newSequenceFlow = new SequenceFlow(); newSequenceFlow.setSourceFlowElement(currentFlowNode); newSequenceFlow.setTargetFlowElement(lastFlowNode); currentFlowNode.setOutgoingFlows(Collections.singletonList(newSequenceFlow)); // 完成任务并恢复原始流向 taskService.complete(task.getId()); currentFlowNode.setOutgoingFlows(originalFlows); }

这种实现存在三个主要问题:

  1. 历史数据依赖风险:需要频繁查询ACT_HI_*历史表,在长流程中性能较差
  2. 并发修改冲突:直接修改内存中的流程定义,多实例同时操作可能导致状态不一致
  3. 事务完整性挑战:如果在complete()和流向恢复之间系统崩溃,流程将处于不一致状态

下表对比了动态改流向方案在不同场景下的表现:

场景成功率平均耗时(ms)数据库锁等待次数
单线程短流程100%1200
100并发短流程92%35017
单线程长流程(20+节点)95%6803
100并发长流程68%120089

2. 基于ProcessInstanceModification的安全驳回方案

Activiti7提供了更官方的流程修改API,RuntimeService.createProcessInstanceModification方法可以实现不依赖历史数据的流程跳转:

public void safeBackProcess(Task task, String targetActivityId) { runtimeService.createProcessInstanceModification(task.getProcessInstanceId()) .cancelActivityInstance(getCurrentActivityInstanceId(task)) .startBeforeActivity(targetActivityId) .execute(); // 可选:设置目标节点处理人 taskService.setAssignee( taskService.createTaskQuery() .processInstanceId(task.getProcessInstanceId()) .active() .singleResult().getId(), getPreviousAssignee(task) ); }

这种实现有以下优势:

  1. 无历史表查询:直接操作运行时数据,避免性能瓶颈
  2. 原子性操作:所有修改在单个事务中完成
  3. 清晰的审计日志:在ACT_RU_EXECUTION中保留完整的跳转记录

关键参数说明:

  • cancelActivityInstance: 终止当前活动的执行实例
  • startBeforeActivity: 在指定节点前创建新执行实例
  • setVariable/setVariables: 可选的变量传递

在同样的压力测试环境下,新方案的表现为:

场景成功率平均耗时(ms)数据库锁等待次数
单线程短流程100%850
100并发短流程100%1100
单线程长流程100%1500
100并发长流程100%1800

3. 会签场景下的特殊驳回处理

会签(多实例任务)的驳回需要特殊处理,因为涉及多个并行实例的状态管理。以下是会签驳回的最佳实践:

public void backFromMultiInstance(Task task, String targetActivityId) { // 获取会签父执行实例 Execution parentExecution = runtimeService.createExecutionQuery() .executionId(task.getExecutionId()) .singleResult() .getParent(); // 终止整个会签活动 runtimeService.createProcessInstanceModification(task.getProcessInstanceId()) .cancelAllForActivity(parentExecution.getActivityId()) .startBeforeActivity(targetActivityId) .execute(); // 重置会签审批人列表 runtimeService.setVariable( parentExecution.getId(), "approverList", getOriginalApprovers(task.getProcessDefinitionId()) ); }

会签驳回的三个关键点:

  1. 批量终止:使用cancelAllForActivity一次性结束所有并行实例
  2. 变量清理:重置会签相关的计数变量(nrOfInstances等)
  3. 审批人重置:恢复原始的审批人列表

4. 性能优化与实施建议

根据实际业务场景选择合适的驳回方案:

  1. 简单审批流:节点数<5,并发量<50TPS → 动态改流向(开发简单)
  2. 复杂业务流程:节点多、并发高 → ProcessInstanceModification(稳定可靠)
  3. 会签场景:必须使用批量终止方式,避免遗留僵尸实例

优化数据库配置:

# 提高ACT_RU_*表的查询效率 spring.datasource.hikari.maximum-pool-size=20 spring.jpa.properties.hibernate.jdbc.batch_size=50 spring.jpa.properties.hibernate.order_updates=true

监控指标建议:

  • activiti.db.sql.count: 每个驳回操作的SQL语句数
  • activiti.lock.wait.time: 锁等待时间
  • activiti.history.level: 适当降低历史级别(如设为audit)
http://www.jsqmd.com/news/909870/

相关文章:

  • 福建省三明CPPMSCMP官网报考入口,官方授权双证报考中心 - 众智商学院课程中心
  • 2026 年 3PE、TPEP、3PP 及输水、重防腐海桩钢管厂家产品性能全面测评 - 栗子测评
  • 导师严选!2026年刚需首选的专业AI智能降重工具 - 降AI小能手
  • 基于Arduino与BMP388的业余火箭高度计DIY全攻略
  • 查重率亮红灯反复修改,有哪些真正亲测好用的的AI智能降重工具推荐? - 降AI小能手
  • 2026吉安市本地人必选的公共卫生检测专业机构TOP5推荐!美容院、足疗店、酒店宾馆卫生检测、许可证办理,正规CMA资质检测公司排名推荐 (2026年5月商铺卫生办证最新深度调研方案) - 一休咨询
  • Android音频转发神器:让手机声音在电脑上完美播放的3种实用方案
  • Allegro PCB Designer Quickplace功能避坑指南:从‘放不全元件’到‘一键搞定’的完整配置流程
  • 2026珲春市本地人必选的公共卫生检测专业机构TOP5推荐!美容院、足疗店、酒店宾馆卫生检测、许可证办理,正规CMA资质检测公司排名推荐 (2026年5月商铺卫生办证最新深度调研方案) - 一休咨询
  • ChatGPT免费版实战指南:从核心能力到工作流集成的AI应用
  • 终极解决方案:破解Navicat Mac版试用限制的三种创新方法
  • 宝安管道疏通|15年本地宋师傅,解决下水道堵塞、马桶反水、地漏返味问题 - GrowthUME
  • 2026淮南市本地人必选的公共卫生检测专业机构TOP5推荐!美容院、足疗店、酒店宾馆卫生检测、许可证办理,正规CMA资质检测公司排名推荐 (2026年5月商铺卫生办证最新深度调研方案) - 一休咨询
  • 衡水恒益奢品汇:深耕本地市场 专业开展名包回收及奢侈品回收服务 - GrowthUME
  • 深圳大型搬迁必看:3步筛选靠谱服务机构 - 幸福生活序曲
  • SPT-AKI存档编辑器:重新定义你的塔科夫单机版游戏体验
  • iPhone电池更换全攻略:从安全拆解到实战技巧
  • 气体/氮气/氢气/空气发生器实力厂家推荐|2026口碑好售后较好的品牌盘点 - 品牌推荐大师1
  • 别再手动K帧了!用UE4 Sequencer让角色从桥下走到桥上,这5个关键帧技巧必须掌握
  • 2026惠州市本地人必选的公共卫生检测专业机构TOP5推荐!美容院、足疗店、酒店宾馆卫生检测、许可证办理,正规CMA资质检测公司排名推荐 (2026年5月商铺卫生办证最新深度调研方案) - 一休咨询
  • 呼和浩特黄金上门回收怎么选?福运来黄金回收稳坐头把交椅 - 黄金回收
  • 爱搜网盘资源搜索:免费无广告免登录,打造极速纯净的资源检索新体验 - GrowthUME
  • 别再死记硬背IIC时序了!通过蓝桥杯开发板的AT24C02,深入理解IIC协议与EEPROM应用
  • CoolProp开源热物理计算库:免费替代商业软件的终极解决方案
  • 全屋定制如何避坑?3分钟看完,不踩雷 - GrowthUME
  • 北京黄金上门回收怎么选?福运来黄金回收专业透明变现快 - 黄金回收
  • BetterNCM插件管理器终极指南:轻松为网易云音乐添加无限可能
  • 自动化时代的工作重塑:从任务解构到人机协同的实战指南
  • 乌鲁木齐黄金上门回收横评,福运来黄金回收凭实力领跑 - 黄金回收
  • 微信立减金快过期怎么办?很多人不知道还能这样回收处理 - 圆圆收