|
|
@@ -2,12 +2,10 @@ 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.health.SystemHealthService;
|
|
|
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;
|
|
|
@@ -15,12 +13,6 @@ 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
|
|
|
@@ -34,10 +26,7 @@ public class ApplicationScheduler {
|
|
|
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("#.##");
|
|
|
+ private final SystemHealthService healthService;
|
|
|
|
|
|
@PreDestroy
|
|
|
public void onShutDown() {
|
|
|
@@ -46,20 +35,10 @@ public class ApplicationScheduler {
|
|
|
|
|
|
@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());
|
|
|
+ if (!this.healthService.checkSystemHealth()) {
|
|
|
+ // 시스템이 과부하이면 처리하지 않는다.
|
|
|
+ return;
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
@@ -107,68 +86,4 @@ public class ApplicationScheduler {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- 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());
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
}
|