You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WildFly下JDBC作业仓库的真实运行作业执行数查询问题

解决WildFly JDBC作业仓库中误报运行作业的问题

这个问题我之前帮不少开发者排查过,核心原因是内存作业仓库和JDBC作业仓库的状态持久化逻辑完全不同:

  • 内存仓库的作业状态只存在于当前JVM进程中,一旦WildFly被强制杀死,所有运行状态都会被清空,重启后自然不会有残留的“假运行”记录。
  • 而JDBC仓库把作业状态存在数据库里,当WildFly被强制终止时,服务器没有机会主动更新数据库中那些正在运行的作业状态(比如把STARTED改成FAILED或ABANDONED),导致重启后JobOperator读取到这些旧的状态记录,误判为仍在运行。

要查询真正处于运行状态的作业执行数量,你可以从以下几个方向入手:

方法一:结合数据库查询与WildFly启动时间过滤

既然假的“运行中”作业都是上一次进程残留的,它们的启动时间肯定早于当前WildFly实例的启动时间。你可以:

  1. 获取当前WildFly的启动时间:

    • 通过JMX控制台连接WildFly,找到jboss.as:management-root=server下的start-time属性;
    • 或者在WildFly启动时,把启动时间写入系统属性(比如在standalone.conf中添加-Dwildfly.start.time=$(date +%s000)),然后在代码中用System.getProperty("wildfly.start.time")获取。
  2. 查询数据库中的有效运行作业:
    WildFly的JDBC Batch仓库默认使用的表(比如JOB_EXECUTION)包含STATUS和START_TIME字段。执行以下SQL统计真正运行的作业:

    SELECT COUNT(*) 
    FROM JOB_EXECUTION 
    WHERE STATUS = 'STARTED' 
      AND START_TIME > ? -- 这里填入当前WildFly的启动时间戳
    

方法二:通过代码验证作业的实际运行状态

你可以通过JobOperator获取所有标记为运行的作业,然后逐个验证它们是否真的在当前JVM中执行:

JobOperator jobOperator = BatchRuntime.getJobOperator();
Set<Long> runningExecutions = jobOperator.getRunningExecutions();
long wildflyStartTime = Long.parseLong(System.getProperty("wildfly.start.time"));
int actualRunningCount = 0;

for (Long executionId : runningExecutions) {
    JobExecution execution = jobOperator.getJobExecution(executionId);
    // 验证两点:启动时间晚于服务器启动时间,且状态确实是STARTED
    if (execution.getStartTime().getTime() > wildflyStartTime 
        && BatchStatus.STARTED.equals(execution.getBatchStatus())) {
        actualRunningCount++;
    }
}

System.out.println("真正运行的作业数量:" + actualRunningCount);

方法三:启动时自动清理残留的无效作业

为了从根源避免这个问题,你可以在WildFly启动时添加一个初始化任务,自动将数据库中状态为STARTED但启动时间早于当前服务器启动时间的作业标记为ABANDONED或FAILED:

// 可以放在@Startup的CDI bean中
@Startup
@Singleton
public class BatchCleanupService {

    @Resource(lookup = "java:jboss/datasources/YourBatchDatasource")
    private DataSource dataSource;

    @PostConstruct
    public void cleanupStaleJobs() {
        long wildflyStartTime = Long.parseLong(System.getProperty("wildfly.start.time"));
        String sql = "UPDATE JOB_EXECUTION SET STATUS = 'ABANDONED' WHERE STATUS = 'STARTED' AND START_TIME < ?";
        
        try (Connection conn = dataSource.getConnection();
             PreparedStatement stmt = conn.prepareStatement(sql)) {
            stmt.setTimestamp(1, new Timestamp(wildflyStartTime));
            int updated = stmt.executeUpdate();
            System.out.println("清理了" + updated + "个残留的无效作业");
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

这样处理后,重启WildFly时旧的残留作业状态会被修正,getRunningExecutions返回的结果就会和实际运行的作业一致了。

内容的提问来源于stack exchange,提问作者mohammad_1m2

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:40:51