Flowable 异步执行器调优指南:定时作业与异步执行的机制全解析
【免费下载链接】flowable-userguideFlowable最新中文文档,ai自动生成BPM体验地址:http://flow.je4.cn/#/login项目地址: https://gitcode.com/gh_mirrors/fl/flowable-userguide
Flowable 异步执行器(Async Executor)是 Flowable 流程引擎在 V6 版本起唯一保留的作业执行器,负责定时器触发与异步作业的后台执行,其性能直接影响高并发场景下的流程吞吐量。本文从零开始,带新手理解 Flowable 定时作业与异步执行的底层机制,并给出可直接落地的异步执行器调优参数建议。
为什么需要异步执行器?⚙️
Flowable 引擎默认以事务方式同步执行流程:一次 API 调用(如完成任务)会沿流程一路执行,直到所有分支都到达"等待状态"才提交事务。这意味着如果流程中有慢操作(如调用外部 HTTP 接口、生成发票),调用线程会被长时间阻塞。
异步执行器正是为了解决这个问题而生的:把服务任务标记为异步后,引擎会先把流程实例持久化、提交事务,再让后台线程池继续执行后续逻辑。用户线程立即获得响应,流程吞吐量大幅提升。
📌 在 Flowable V6 中,V5 时代的旧版作业执行器(Job Executor)已完全移除,异步执行器是唯一选择,详见官方配置章节 ch03-Configuration.adoc。
两类核心作业:定时器作业与异步作业
异步执行器管理着两种作业类型,它们存储在不同的数据库表中:
| 作业类型 | 存储表 | 产生方式 | 触发条件 |
|---|---|---|---|
| 定时器作业(Timer Job) | ACT_RU_TIMER_JOB | 定时器边界事件、定时器启动事件、定时器中间事件 | 到期时间到达 |
| 异步作业(Async Job) | ACT_RU_JOB | 标记了flowable:async="true"的服务任务等 | 被异步执行器锁定并获取 |
| 死信作业(Dead Letter Job) | ACT_RU_DEADLETTER_JOB | 重试超过上限的失败作业 | 等待人工排查 |
异步执行器中有一个专门的线程周期性扫描定时器作业,到期后将其转换为异步作业并交给线程池执行;另一个线程负责"获取"未被锁定的异步作业,加锁后送入内存队列,由执行线程池真正跑起来。
同步与异步的直观对比
先看默认的同步执行:用户任务、服务任务与定时器事件全部挤在同一个事务中,任何一个环节失败都会整体回滚。
而把服务任务标记为异步后,事务被拆分:用户任务完成后立即提交并返回,发票生成等重活交给后台"作业执行器线程"独立执行,两个事务互不影响:
实现方式很简单,只需给服务任务加上flowable:async="true"属性,完整 XML 示例见 ch07b-BPMN-Constructs.adoc。
第一步:开启异步执行器 🔑
异步执行器默认是关闭的,定时器也因此不会触发。启用只需在流程引擎配置中设置一个开关:
<property name="asyncExecutorActivate" value="true" />Java 配置方式:
configuration.setAsyncExecutorActivate(true);Spring Boot 场景下同样可以通过SpringProcessEngineConfiguration开启,参考 ch05a-Spring-Boot.adoc。
⚠️ 新手最容易踩的坑:部署了带定时器边界事件的流程却迟迟不触发,九成是因为没有打开
asyncExecutorActivate!
核心调优参数:一张表看懂异步执行器配置
异步执行器高度可配置,官方完整参数表在 ch17-Advanced.adoc。以下是最常用的调优项:
| 参数 | 默认值 | 调优建议 |
|---|---|---|
asyncExecutorCorePoolSize | 2 | 执行作业线程池的核心线程数,高并发可调至 4~8 |
asyncExecutorMaxPoolSize | 10 | 最大线程数,结合机器核数与作业量调整 |
asyncExecutorThreadPoolQueueSize | 100 | 内存作业队列长度,队列满时作业会解锁回写数据库 |
asyncExecutorMaxTimerJobsPerAcquisition | 1 | 单次查询获取的定时器作业数,调大可提升吞吐但乐观锁冲突概率上升 |
asyncExecutorMaxAsyncJobsDuePerAcquisition | 1 | 单次查询获取的异步作业数,含义同上 |
asyncExecutorDefaultTimerJobAcquireWaitTime | 10000 | 定时器作业两次查询间隔(毫秒),空闲时生效 |
asyncExecutorDefaultAsyncJobAcquireWaitTime | 10000 | 异步作业两次查询间隔(毫秒) |
asyncExecutorTimerLockTimeInMillis | 300000 | 定时器作业锁定时长(5 分钟),锁超时后其他执行器可重新获取 |
asyncExecutorAsyncJobLockTimeInMillis | 300000 | 异步作业锁定时长(5 分钟) |
asyncExecutorResetExpiredJobsInterval | 60000 | 解锁"超时作业"的检查间隔(秒),用于恢复卡死的作业 |
asyncExecutorNumberOfRetries | 3 | 作业最大重试次数,超过后进入死信表 |
asyncExecutorSecondsToWaitOnShutdown | 60 | 引擎关闭时等待线程池安全退出时间 |
调优口诀 💡
- 作业多、跑得慢:优先调大
MaxAsyncJobsDuePerAcquisition与线程池大小; - 乐观锁异常频繁:把单次获取数量调回 1,降低多引擎竞争;
- 作业卡死无人管:缩短
LockTimeInMillis或ResetExpiredJobsInterval,让超时作业更快被"解锁复活"。
失败重试与死信作业机制
作业执行失败时,Flowable 会自动把它转成带到期日期的定时器作业,等待下一次获取重试。重试次数超过asyncExecutorNumberOfRetries(默认 3 次)后,作业会被移入ACT_RU_DEADLETTER_JOB死信表,等待管理员排查异常并人工处理。
这种"重试 → 死信"的设计与消息队列的 dead letter 概念一脉相承,可以防止故障作业无限占用线程池资源。
进阶方案:基于消息队列的异步执行器 🚀
如果线程池模式仍无法满足吞吐要求,Flowable 还提供了基于消息队列的异步执行器实现:新作业产生时向 MQ 发送一条含作业 ID 的消息,消费者取到 ID 后获取并执行作业,彻底摆脱轮询数据库的瓶颈。官方支持通过flowable-jms-spring-executor配合 ActiveMQ 使用,开启方式为:
asyncExecutorActivate = trueasyncExecutorMessageQueueMode = true- 注入
MessageBasedJobManager作为JobManager
跑分显示消息队列模式吞吐量显著优于线程池模式,代价是需要引入额外的中间件与运维复杂度——对于大多数业务场景,默认线程池模式已经足够。
监控作业运行状态
作业是否在跑、是否堆积,可以通过 Flowable 自带的管理界面查看。作业管理页面会列出定时器作业、异步作业与死信作业的实时状态,是排查"定时器不触发"和"作业卡死"问题的最直观入口。
总结
Flowable 异步执行器是流程引擎后台能力的核心:理解定时器作业与异步作业的区分、掌握asyncExecutorActivate的开启方式、熟读上表中的调优参数,你就能从"定时器不触发"的新手困境中走出来,一步步把高并发流程的吞吐量调到最佳状态。更多细节可继续阅读用户手册中的 ch03-Configuration.adoc 与 ch17-Advanced.adoc。
【免费下载链接】flowable-userguideFlowable最新中文文档,ai自动生成BPM体验地址:http://flow.je4.cn/#/login项目地址: https://gitcode.com/gh_mirrors/fl/flowable-userguide
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考