在使用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及以上版本,可以有效减轻数据库负担并提高系统性能。

这个解决方案的核心思想是:当配置文件不生效时,直接修改运行时对象是解决问题的有效途径。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐