我想创建两个返回相同 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,但也不起作用。这是什么原因以及如何解决?
通过调用
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() {
...
}