Activiti7频繁轮询ACT_RU_TIMER_JOB和ACT_RU_JOB 数据库
在使用Activiti工作流引擎的Spring Boot项目中,经常会遇到一个困扰的问题:Activiti会频繁查询ACT_RU_TIMER_JOB和ACT_RU_JOB表,每10秒一次,这不仅增加了数据库压力,还会在日志中产生大量的查询记录。
这篇博客将详细介绍如何通过运行时修改Activiti配置来解决这个问题。
博主环境:idea2022+Activiti7(7.1.0.M3.1)
问题现象
在Activiti项目运行时,你可能会在日志中看到类似以下的频繁查询:

这些查询大约每10秒执行一次,默认情况下无法通过常规配置方式修改。
尝试过的不生效方案
通常我们会尝试在application.yml中添加配置:
spring:
activiti:
async-executor-activate: true
job-executor-activate: true
async:
executor:
default-async-job-acquire-wait-time-in-millis: 60000
default-timer-job-acquire-wait-time-in-millis: 60000
但实际上这些配置很可能不生效,原因是Activiti在创建执行器时可能忽略这些配置,或者使用了默认值。
终极解决方案
最有效的方案是通过Java配置类,在Bean初始化后直接修改运行中的执行器实例:
package com.community.config;
import org.activiti.engine.impl.asyncexecutor.DefaultAsyncJobExecutor;
import org.activiti.spring.SpringProcessEngineConfiguration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
/**
* Activiti配置类 - 用于调整作业执行器的轮询间隔
*/
@Configuration
public class ActivitiConfig {
/**
* 注入Spring自动创建的ProcessEngineConfiguration实例
* 这是实际运行的配置对象,不是新创建的
*/
@Autowired
private SpringProcessEngineConfiguration processEngineConfiguration;
/**
* 在Bean初始化完成后执行
* 直接修改已经创建好的执行器实例
*/
@PostConstruct
public void init() {
// 获取当前执行器并修改配置
if (processEngineConfiguration.getAsyncExecutor() != null) {
DefaultAsyncJobExecutor jobExecutor =
(DefaultAsyncJobExecutor) processEngineConfiguration.getAsyncExecutor();
// 设置轮询间隔为60秒(60000毫秒)
jobExecutor.setDefaultTimerJobAcquireWaitTimeInMillis(60000);
jobExecutor.setDefaultAsyncJobAcquireWaitTimeInMillis(60000);
// 设置锁定时间为5分钟
jobExecutor.setTimerLockTimeInMillis(300000);
jobExecutor.setAsyncJobLockTimeInMillis(300000);
// 尝试设置可能存在的其他配置
try {
// 这些方法在不同版本的Activiti中可能不存在
// 使用反射尝试调用,忽略可能的异常
jobExecutor.getClass().getMethod("setMaxTimerJobsPerAcquisition", int.class)
.invoke(jobExecutor, 1);
jobExecutor.getClass().getMethod("setMaxAsyncJobsPerAcquisition", int.class)
.invoke(jobExecutor, 1);
} catch (Exception e) {
// 忽略不支持的方法
}
// 设置线程池大小
jobExecutor.setCorePoolSize(2);
}
}
/**
* 可选:定义自己的执行器
* 但这个方法可能不会被使用,因为Activiti可能会创建自己的执行器
*/
@Bean
public DefaultAsyncJobExecutor asyncExecutor() {
DefaultAsyncJobExecutor asyncExecutor = new DefaultAsyncJobExecutor();
asyncExecutor.setDefaultTimerJobAcquireWaitTimeInMillis(60000);
asyncExecutor.setDefaultAsyncJobAcquireWaitTimeInMillis(60000);
asyncExecutor.setTimerLockTimeInMillis(300000);
asyncExecutor.setAsyncJobLockTimeInMillis(300000);
asyncExecutor.setCorePoolSize(2);
return asyncExecutor;
}
}
为什么这个方案有效?
这个解决方案生效的关键在于四个方面:
1. @PostConstruct生命周期钩子
@PostConstruct注解确保方法在Bean完全初始化后、投入使用前执行。这比普通Bean的创建时机更晚,能够修改已经被Spring容器创建和管理的组件。
2. 直接访问运行时实例
通过@Autowired注入的是Spring容器中实际使用的SpringProcessEngineConfiguration实例,而不是创建新的配置对象。这是关键点——我们直接修改的是系统实际运行的配置,而不是创建一个新的配置。
3. 运行时修改配置
获取实际使用的AsyncExecutor实例并直接修改其属性,这些更改会立即生效,因为它们修改的是已经被容器管理的活跃对象。相当于在汽车行驶过程中调整了发动机参数,而不是在设计图上做修改。
4. 健壮的异常处理
使用反射机制尝试设置可能不存在的方法,并优雅地处理可能的异常,确保即使某些配置方法在特定Activiti版本中不存在,也不会影响配置的整体应用。
配置参数说明
- defaultTimerJobAcquireWaitTimeInMillis: 定时作业轮询间隔(毫秒)
- defaultAsyncJobAcquireWaitTimeInMillis: 异步作业轮询间隔(毫秒)
- timerLockTimeInMillis: 定时作业锁定时间(毫秒)
- asyncJobLockTimeInMillis: 异步作业锁定时间(毫秒)
- corePoolSize: 执行线程池的核心线程数
效果
应用这个配置后,Activiti的轮询频率将从默认的10秒变为60秒,显著减少数据库查询次数,降低系统资源消耗。
总结
通过直接修改运行时的Activiti配置实例,我们能够有效地调整作业执行器的轮询间隔,避开了通过配置文件可能被忽略的问题。这种方法适用于Activiti 7及以上版本,可以有效减轻数据库负担并提高系统性能。
这个解决方案的核心思想是:当配置文件不生效时,直接修改运行时对象是解决问题的有效途径。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)