| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- package com.evps.comm.server.scheduler;
- import com.evps.comm.server.config.ApplicationConfig;
- import com.evps.comm.server.config.TraceConfig;
- import com.evps.comm.server.repository.ApplicationRepository;
- import com.evps.comm.server.service.EvpsServiceManagerService;
- import com.evps.comm.server.service.UnitSystService;
- import com.evps.common.utils.SystemHealth;
- import com.zaxxer.hikari.HikariDataSource;
- import com.zaxxer.hikari.HikariPoolMXBean;
- import lombok.RequiredArgsConstructor;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.scheduling.annotation.EnableScheduling;
- import org.springframework.scheduling.annotation.Scheduled;
- import org.springframework.stereotype.Component;
- import javax.annotation.PreDestroy;
- import java.lang.management.ManagementFactory;
- import java.lang.management.ThreadInfo;
- import java.lang.management.ThreadMXBean;
- import java.text.DecimalFormat;
- import java.util.EnumMap;
- import java.util.Map;
- @Slf4j
- @RequiredArgsConstructor
- @EnableScheduling
- @Component
- public class ApplicationScheduler {
- private final TraceConfig traceConfig;
- private final ApplicationConfig config;
- private final UnitSystService unitSystService;
- private final ApplicationRepository applicationRepository;
- private final EvpsServiceManagerService evpsServiceManagerService;
- private final HikariDataSource dataSource;
- private final Map<Thread.State, Integer> stateCountMap = new EnumMap<>(Thread.State.class);
- private final SystemHealth systemHealth = new SystemHealth();
- private final DecimalFormat df = new DecimalFormat("#.##");
- @PreDestroy
- public void onShutDown() {
- log.info("ApplicationScheduler.onShutDown: Shutting down...");
- }
- @Scheduled(cron = "0 * * * * *")
- public void updateProcessState() {
- try {
- this.systemHealth.checkHealth(false);
- loggingHealthCheck();
- double cpuUsage = this.systemHealth.getCpuUsage();
- if (cpuUsage > this.config.getCpuLimits()) {
- // ApplicationRepository.processState.setErrDesc("CPU 사용율이 너무 높음: " + String.format("%.2f", cpuUsage));
- log.warn("[SKIP] ApplicationScheduler.updateProcessState: High CPU Usage, Limit({} %), Current({} %), Schedule Job SKIP...",
- this.config.getCpuLimits(), String.format("%.2f", cpuUsage));
- loggingThreads();
- return;
- }
- } catch (Exception e) {
- log.error("ApplicationScheduler.updateProcessState: System Health Check Exception {}", e.getMessage());
- }
- try {
- this.unitSystService.updateUnitSystStts();
- }
- catch(Exception e) {
- log.error("ApplicationScheduler.updateProcessState: Exception {}", e.getMessage());
- }
- try {
- this.traceConfig.loadTraceInfo();
- }
- catch(Exception e) {
- log.error("ApplicationScheduler.loadTraceInfo: Exception {}", e.getMessage());
- }
- }
- @Scheduled(cron = "0/30 * * * * *")
- public void serviceMangerSchedule() {
- try {
- this.evpsServiceManagerService.checkServiceTimeout();
- }
- catch(Exception e) {
- log.error("ApplicationScheduler.serviceMangerSchedule: Exception {}", e.getMessage());
- }
- }
- @Scheduled(cron = "20 * * * * *") // 1분주기 작업 실행
- public void reportCenterSessions() {
- try {
- this.applicationRepository.reportCenterSessions();
- }
- catch(Exception e) {
- log.error("ApplicationScheduler.reportCenterSessions: Exception {}", e.getMessage());
- }
- }
- @Scheduled(cron = "10 0/5 * * * *") // 5분주기 작업 실행
- public void loadBaseDatabase() {
- try {
- this.applicationRepository.loadDb();
- }
- catch(Exception e) {
- log.error("ApplicationScheduler.loadBaseDatabase: Exception {}", e.getMessage());
- }
- }
- private void loggingHealthCheck() {
- log.info("----------------------------------------------------------------------------------------------------------");
- loggingSystemHealth();
- logSessionStatus();
- loggingThreadState();
- log.info("----------------------------------------------------------------------------------------------------------");
- }
- private void loggingSystemHealth() {
- double loadAvg = this.systemHealth.getLoadAverage();
- String loadAvgStr = (loadAvg < 0) ? "N/A" : this.df.format(loadAvg);
- log.info("SYSTEM HEALTH: CPU {} Cores[{} %, LoadAvg({})], Memory[{} %, Used({} MB), Max({} MB)], Threads[{}, Peak({})], GC(T/R)[{}/{} ms]",
- this.systemHealth.getCpuCores(),
- this.df.format(this.systemHealth.getCpuUsage()),
- loadAvgStr,
- this.df.format(this.systemHealth.getMemUsage()),
- this.systemHealth.getUsedMemory(),
- this.systemHealth.getMaxMemory(),
- this.systemHealth.getThreadCount(),
- this.systemHealth.getPeakThreadCount(),
- this.systemHealth.getGcTotalAvgTime(),
- this.systemHealth.getGcRecentAvgTime());
- }
- private void logSessionStatus() {
- HikariPoolMXBean poolStats = this.dataSource.getHikariPoolMXBean();
- int totalConnections = poolStats.getTotalConnections();
- int activeConnections = poolStats.getActiveConnections();
- int idleConnections = poolStats.getIdleConnections();
- int threadsAwaiting = poolStats.getThreadsAwaitingConnection();
- log.info(" DB SESSION: Total: {}, Active: {}, Idle: {}, Waiting: {}",
- totalConnections, activeConnections, idleConnections, threadsAwaiting);
- }
- private void loggingThreadState() {
- ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
- ThreadInfo[] infos = threadBean.dumpAllThreads(false, false);
- this.stateCountMap.clear();
- for (ThreadInfo info : infos) {
- Thread.State state = info.getThreadState();
- this.stateCountMap.put(state, this.stateCountMap.getOrDefault(state, 0) + 1);
- }
- StringBuilder sb = new StringBuilder();
- for (Map.Entry<Thread.State, Integer> entry : stateCountMap.entrySet()) {
- sb.append(String.format("%s(%d), ", entry.getKey().name(), entry.getValue()));
- }
- // 마지막 쉼표 제거
- if (sb.length() > 0) {
- sb.setLength(sb.length() - 2);
- }
- log.info(" THREAD STATE: {}", sb.toString());
- }
- private void loggingThreads() {
- ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
- ThreadInfo[] infos = threadBean.dumpAllThreads(false, false);
- this.stateCountMap.clear();
- for (ThreadInfo info : infos) {
- Thread.State state = info.getThreadState();
- this.stateCountMap.put(state, this.stateCountMap.getOrDefault(state, 0) + 1);
- log.info(" [" + info.getThreadId() + "] " + info.getThreadName() + " - " + info.getThreadState());
- }
- }
- }
|