定义了两个 ThreadPoolTaskScheduler beans,但所有计划任务都在其中一个上运行

问题描述 投票:0回答:1

我想创建两个返回相同 obj 类型的 bean:

    @SuppressWarnings("unused")
    @Configuration
    @EnableScheduling
    public class SchedulingConfig {


    @Bean(name = "schedulerHikari")
    public ThreadPoolTaskScheduler schedulerHikari() {
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setPoolSize(1);
        scheduler.setThreadNamePrefix("scheduler-hikari-hc-");
        return scheduler;
    }


    @Bean(name = "schedulerJVM")
    public ThreadPoolTaskScheduler schedulerJVM() {
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setPoolSize(1);
        scheduler.setThreadNamePrefix("scheduler-jvm-hc-");
        return scheduler;
    }
}

创建 healthCheck 类:

    @Component
    @AllArgsConstructor
    @Slf4j
    @SuppressWarnings("unused")
    public class HikariCPCheck implements ApplicationListener<ContextRefreshedEvent>,         SchedulingConfigurer {

    private final HikariDataSource dataSource;
    @Qualifier("schedulerHikari")
    private final ThreadPoolTaskScheduler schedulerHikari;
    @Value("${healthcheck.datasource.hikari.max-awaiting}")
    private final int maxAwaitingConnections;
    @Value("${healthcheck.datasource.hikari.scheduler-hikari-delay}")
    private final int initialDelay;
    @Value("${healthcheck.datasource.hikari.scheduler-hikari-rate}")
    private final int fixedRate;

    @Override
    public void onApplicationEvent(@NonNull ContextRefreshedEvent event) {
        try (Connection connection = dataSource.getConnection()) {
            log.info("Successfully obtained connection from HikariCP");
        } catch (SQLException e) {
            if (e.getMessage().contains("Timeout")) {
                log.error("HikariCP pool initialization failed: Connection timeout", e);
            } else {
                log.error("Failed to obtain connection from HikariCP", e);
            }
        }
    }

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.setScheduler(schedulerHikari);
        PeriodicTrigger trigger = new PeriodicTrigger(Duration.ofMinutes(fixedRate));
        trigger.setInitialDelay(Duration.ofMinutes(initialDelay));
        taskRegistrar.addTriggerTask(
                this::logConnectionPoolStatus,
                trigger
        );
    }

    private void logConnectionPoolStatus() {
        HikariPoolMXBean hikariPoolMXBean = dataSource.getHikariPoolMXBean();
        HikariConfigMXBean hikariConfigMXBean = dataSource.getHikariConfigMXBean();

        log.info("HikariCP Pool Name: {}", dataSource.getPoolName());
        log.info("HikariCP Total Connections: {}", hikariPoolMXBean.getTotalConnections());
        if (hikariPoolMXBean.getActiveConnections() >= hikariConfigMXBean.getMaximumPoolSize()) {
            log.warn("HikariCP Active Connections reached max pool size {active connections: {}, max pool size: {}}.", hikariPoolMXBean.getActiveConnections(), hikariConfigMXBean.getMaximumPoolSize());
        } else {
            log.info("HikariCP Active Connections: {active connections: {}, max pool size: {}}.", hikariPoolMXBean.getActiveConnections(), hikariConfigMXBean.getMaximumPoolSize());
        }
        log.info("HikariCP Idle Connections: {}.", hikariPoolMXBean.getIdleConnections());
        if (hikariPoolMXBean.getThreadsAwaitingConnection() > maxAwaitingConnections) {
            log.error("HikariCP Threads Awaiting Connection greater then limit {awaiting threads: {}, max: {}}.", hikariPoolMXBean.getThreadsAwaitingConnection(), maxAwaitingConnections);
        } else {
            log.info("HikariCP Threads Awaiting Connection: {awaiting threads: {}, max: {}}.", hikariPoolMXBean.getThreadsAwaitingConnection(), maxAwaitingConnections);
        }
    }
}

第二课:

    @Component
    @AllArgsConstructor
    @Slf4j
    @SuppressWarnings("unused")
    public class JVMHealthCheck implements SchedulingConfigurer{

    private final OperatingSystemMXBean osMXBean = (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
    private final MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
    @Qualifier("schedulerJVM")
    private final ThreadPoolTaskScheduler schedulerJVM;
    @Value("${healthcheck.jvm.processor.threshold}")
    private final int processorThreshold;
    @Value("${healthcheck.jvm.heap-memory.threshold}")
    private final int heapMemoryThreshold;
    @Value("${healthcheck.jvm.non-heap-memory.threshold}")
    private final int nonHeapMemoryThreshold;
    @Value("${healthcheck.jvm.scheduler-jvm-delay}")
    private final int initialDelay;
    @Value("${healthcheck.jvm.scheduler-jvm-rate}")
    private final int fixedRate;

    @PostConstruct
    public void logConnectionConfigStatus() {
        MemoryUsage heapMemoryUsage = memoryMXBean.getHeapMemoryUsage();
        log.info("JVM Available Processors: {}", osMXBean.getAvailableProcessors());
        log.info("JVM Init Heap Memory Usage: {}", memoryMXBean.getHeapMemoryUsage().getInit() / (1024 * 1024));
        log.info("JVM Max Heap Memory Usage: {}", memoryMXBean.getHeapMemoryUsage().getMax() / (1024 * 1024));
        log.info("JVM Init Non Heap Memory Usage: {}", memoryMXBean.getNonHeapMemoryUsage().getInit() / (1024 * 1024));
        log.info("JVM Committed Non Heap Memory Usage: {}", memoryMXBean.getNonHeapMemoryUsage().getCommitted() / (1024 * 1024));
    }


    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.setScheduler(schedulerJVM);
        PeriodicTrigger trigger = new PeriodicTrigger(Duration.ofMinutes(fixedRate));
        trigger.setInitialDelay(Duration.ofMinutes(initialDelay));
        taskRegistrar.addTriggerTask(
                this::logJVMUsageStatus,
                trigger
        );
    }

    private void logJVMUsageStatus() {
        log.error("wtf");
        if (osMXBean.getProcessCpuLoad()*100 > processorThreshold) {
            log.warn("JVM Process CPU usage reached threshold {usage: {}, threshold: {}}.", osMXBean.getProcessCpuLoad()*100, processorThreshold);
        }
        if (osMXBean.getProcessCpuLoad()*100 >= 99) {
            log.error("JVM Process CPU usage reached max {usage: {}, max: 100}.", osMXBean.getProcessCpuLoad()*100);
        }

        MemoryUsage heapMemoryUsage = memoryMXBean.getHeapMemoryUsage();
        double usedHeapMemory = (double) heapMemoryUsage.getUsed() / heapMemoryUsage.getMax();
        double roundedHeapMemoryPercentage = Math.round(usedHeapMemory * 100 * 100.0) / 100.0;

        if (roundedHeapMemoryPercentage > heapMemoryThreshold) {
            log.warn("JVM Heap Memory usage reached threshold {usage: {}, threshold: {}}.", memoryMXBean.getHeapMemoryUsage().getUsed() / memoryMXBean.getHeapMemoryUsage().getMax(), heapMemoryThreshold);
        }
        if (roundedHeapMemoryPercentage >= 99) {
            log.warn("JVM Heap Memory usage reached max {usage: {}, max: {}}.", roundedHeapMemoryPercentage, heapMemoryUsage.getMax());
        }

        MemoryUsage nonHeapMemoryUsage = memoryMXBean.getNonHeapMemoryUsage();
        double usedNonHeapMemory = (double) nonHeapMemoryUsage.getUsed() / nonHeapMemoryUsage.getMax();
        double roundedNonHeapMemoryPercentage = Math.round(usedNonHeapMemory * 100 * 100.0) / 100.0;

        if (roundedNonHeapMemoryPercentage > nonHeapMemoryThreshold) {
            log.warn("JVM Non Heap Memory usage reached threshold {usage: {}, threshold: {}}.",  roundedNonHeapMemoryPercentage, nonHeapMemoryThreshold);
        }
        if (roundedNonHeapMemoryPercentage >= 99) {
            log.warn("JVM Non Heap Memory usage reached max {usage: {}, max: {}}.", roundedNonHeapMemoryPercentage, nonHeapMemoryUsage.getMax());
        }
    }

    }

lombok.config:

lombok.copyableAnnotations+=org.springframework.beans.factory.annotation.Qualifier

应用程序属性:

spring.main.allow-bean-definition-overriding=false

但是所有任务都在一个调度程序的一个线程上运行:

2024-10-17 20:43:28,682 INFO  [scheduler-jvm-hc-1] b.c.h.HikariCPCheck: HikariCP Pool Name: name
2024-10-17 20:43:28,682 INFO  [scheduler-jvm-hc-1] b.c.h.HikariCPCheck: HikariCP Total Connections: 10
2024-10-17 20:43:28,682 INFO  [scheduler-jvm-hc-1] b.c.h.HikariCPCheck: HikariCP Active Connections: {active connections: 1, max pool size: 10}.
2024-10-17 20:43:28,683 INFO  [scheduler-jvm-hc-1] b.c.h.HikariCPCheck: HikariCP Idle Connections: 9.
2024-10-17 20:43:28,683 INFO  [scheduler-jvm-hc-1] b.c.h.HikariCPCheck: HikariCP Threads Awaiting Connection: {awaiting threads: 0, max: 3}.
2024-10-17 20:43:28,684 ERROR [scheduler-jvm-hc-1] b.c.h.JVMHealthCheck: wtf

我尝试为两个 bean 使用单独的组件类 - 不起作用。我尝试使用@Resource,但也不起作用。这是什么原因以及如何解决?

java spring
1个回答
0
投票

通过调用

ScheduledTaskRegistrar.setScheduler()
您可以设置默认调度程序。一旦您创建了默认调度程序
schedulerHikari
,第二次将其更改为
schedulerJVM
。如果您想使用不同的调度程序,在
@Scheduled
注释中指定它们会更容易。


@Scheduled(scheduler = "schedulerJVM", fixedRateString = "${healthcheck.jvm.scheduler-jvm-rate}", initialDelayString = "${healthcheck.jvm.scheduler-jvm-delay}")
public void logJVMUsageStatus() {
...
}


@Scheduled(scheduler = "schedulerHikari", fixedRateString = "${healthcheck.datasource.hikari.scheduler-hikari-rate}", initialDelayString = "${healthcheck.datasource.hikari.scheduler-hikari-delay}")
public void logConnectionPoolStatus() {
...
}

© www.soinside.com 2019 - 2024. All rights reserved.