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

如何从代码获取Spring Boot的/actuator/quartz指标实现存活健康指示器?

实现基于Quartz触发器时间的Spring Boot健康指示器

问题背景

需要实现一个健康指示器,在Spring Boot 2.6.7应用内部获取Quartz触发器的previousFireTime和nextFireTime信息,以此检测Job的execute方法随机停止执行的问题。此前尝试从MeterRegistry获取Quartz相关指标但未找到。

解决方案步骤

1. 启用Quartz Actuator端点(可选)

若要依赖Actuator端点数据,先在配置文件中开启Quartz端点:

management.endpoints.web.exposure.include=quartz
management.endpoint.quartz.enabled=true

2. 直接通过Quartz核心API获取触发器信息(推荐)

不依赖Actuator端点,直接调用Quartz调度器API获取实时触发时间,更可靠且无端点暴露限制:

import org.quartz.*;
import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;

import java.time.Instant;
import java.time.temporal.ChronoUnit;

@Component
public class QuartzJobHealthIndicator implements HealthIndicator {

    private final Scheduler scheduler;

    // 注入Quartz调度器实例
    public QuartzJobHealthIndicator(Scheduler scheduler) {
        this.scheduler = scheduler;
    }

    @Override
    public Health health() {
        Health.Builder healthBuilder = Health.up();
        try {
            // 替换为你的Job对应的触发器组和名称
            String triggerGroup = "YOUR_TRIGGER_GROUP";
            String triggerName = "YOUR_TRIGGER_NAME";

            Trigger trigger = scheduler.getTrigger(new TriggerKey(triggerName, triggerGroup));
            if (trigger != null) {
                // 转换为Instant类型便于时间计算
                Instant previousFireTime = trigger.getPreviousFireTime() != null ? trigger.getPreviousFireTime().toInstant() : null;
                Instant nextFireTime = trigger.getNextFireTime() != null ? trigger.getNextFireTime().toInstant() : null;

                healthBuilder.withDetail("previousFireTime", previousFireTime);
                healthBuilder.withDetail("nextFireTime", nextFireTime);

                // 自定义健康检查逻辑:示例为判断上次触发是否超出2倍调度间隔
                if (previousFireTime != null && trigger instanceof CronTrigger) {
                    CronTrigger cronTrigger = (CronTrigger) trigger;
                    long intervalSeconds = cronTrigger.getCronExpression().getExpressionSummary().getIntervalInSeconds();
                    if (ChronoUnit.SECONDS.between(previousFireTime, Instant.now()) > intervalSeconds * 2) {
                        healthBuilder = Health.down().withDetail("reason", "Job未按预期执行,上次触发时间已超出2倍调度间隔");
                    }
                }
            } else {
                healthBuilder = Health.down().withDetail("reason", "未找到指定的触发器");
            }
        } catch (SchedulerException e) {
            healthBuilder = Health.down(e).withDetail("reason", "获取Quartz触发器信息失败");
        }
        return healthBuilder.build();
    }
}

3. 关于MeterRegistry无Quartz指标的说明

Spring Boot 2.6.7默认不会自动注册Quartz相关Metrics,需手动配置开启:

import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.boot.actuate.autoconfigure.metrics.QuartzMetricsAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class QuartzMetricsConfig {

    @Bean
    public QuartzMetricsAutoConfiguration.QuartzMetricsBinder quartzMetricsBinder(Scheduler scheduler, MeterRegistry meterRegistry) {
        return new QuartzMetricsAutoConfiguration.QuartzMetricsBinder(scheduler, meterRegistry);
    }
}

开启后会生成quartz.triggers类计数指标(如触发次数、错过次数),但不包含previousFireTime和nextFireTime,因此仍推荐使用Scheduler API获取目标数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 17:02:43