Browse Source

update controller service

shjung 3 days ago
parent
commit
709047cd08

+ 24 - 1
conf/evps-comm-server.yml

@@ -13,4 +13,27 @@ application:
 
 logging:
   file:
-    path: ${user.dir}/logs/evps-comm-server/
+    path: ${user.home}/logs/evps-comm-server/
+
+---
+spring:
+  config:
+    activate:
+      on-profile: prod
+  datasource:
+    hikari:
+      driver-class-name: org.mariadb.jdbc.Driver
+      jdbc-url: jdbc:mariadb://10.4.4.20:3306/cvim_db?characterEncoding=UTF-8&serverTimezone=Asia/Seoul
+      #jdbc-url: jdbc:mariadb:replication://10.4.4.20:3306,10.4.4.21:3306/cvim_db?characterEncoding=UTF-8&serverTimezone=Asia/Seoul&useServerPrepStmts=true&failoverEnable=true
+      #jdbc-url: jdbc:mariadb://10.4.4.20:3306,10.4.4.21:3306/cvim_db?useServerPrepStmts=true&characterEncoding=UTF-8&serverTimezone=Asia/Seoul
+      # FOR MaxScale
+      #jdbc-url: jdbc:mariadb://10.4.4.30:4006/cvim_db?characterEncoding=UTF-8&serverTimezone=Asia/Seoul&useServerPrepStmts=true
+
+      #jdbc-url: jdbc:mariadb://10.4.4.20:4006,10.4.4.21:4006/cvim_db?useServerPrepStmts=true&characterEncoding=UTF-8&serverTimezone=Asia/Seoul
+      #jdbc-url: jdbc:mariadb://10.4.4.20:4006,10.4.4.21:4006/cvim_db?useServerPrepStmts=true&characterEncoding=UTF-8&serverTimezone=Asia/Seoul
+      #jdbc-url: jdbc:mariadb://10.4.4.20:3306,10.4.4.21:3306/cvim_db?failoverEnable=true
+
+      ### 맥스트케일
+      #jjdbc-url: dbc:mariadb://10.4.4.20:4006,10.4.4.21:4006/cvim_db?useServerPrepStmts=true&characterEncoding=UTF-8&serverTimezone=Asia/Seoul&failoverEnable=true
+      username: cvim
+      password: 44Klctest$$

+ 1 - 1
evps-comm-server/src/main/java/com/evps/comm/server/controller/EvpsCommServerController.java

@@ -25,7 +25,7 @@ public class EvpsCommServerController {
     @GetMapping(value = "", produces = {"application/json; charset=utf8"})
     public String info() {
         String sep = System.lineSeparator();
-        String heading = "----------------------------------------------------------------------------------------------------------------------s";
+        String heading = "----------------------------------------------------------------------------------------------------------------------";
 
         EvpsCenter center = ApplicationRepository.center;
 

+ 114 - 0
evps-comm-server/src/main/java/com/evps/comm/server/health/SystemHealthService.java

@@ -0,0 +1,114 @@
+package com.evps.comm.server.health;
+
+import com.evps.comm.server.config.ApplicationConfig;
+import com.evps.common.utils.SystemHealth;
+import com.zaxxer.hikari.HikariDataSource;
+import com.zaxxer.hikari.HikariPoolMXBean;
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+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
+@Getter
+@Service
+@RequiredArgsConstructor
+public class SystemHealthService {
+
+    private final ApplicationConfig config;
+    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("#.##");
+
+    public boolean checkSystemHealth() {
+        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] SystemHealthService.checkSystemHealth: High CPU Usage, Limit({} %), Current({} %), Schedule Job SKIP...",
+                        this.config.getCpuLimits(), String.format("%.2f", cpuUsage));
+                loggingThreads();
+                return false;
+            }
+        } catch (Exception e) {
+            log.error("SystemHealthService.checkSystemHealth: Exception {}", e.getMessage());
+        }
+        return true;
+    }
+
+    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());
+        }
+    }
+
+}

+ 5 - 90
evps-comm-server/src/main/java/com/evps/comm/server/scheduler/ApplicationScheduler.java

@@ -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());
-        }
-    }
-
 }

+ 2 - 2
evps-comm-server/src/main/resources/application.yml

@@ -111,9 +111,9 @@ spring:
   datasource:
     hikari:
       driver-class-name: org.mariadb.jdbc.Driver
-      #jdbc-url: jdbc:mariadb://10.4.4.20:3306/cvim_db?characterEncoding=UTF-8&serverTimezone=Asia/Seoul
+      jdbc-url: jdbc:mariadb://10.4.4.20:3306/cvim_db?characterEncoding=UTF-8&serverTimezone=Asia/Seoul
       #jdbc-url: jdbc:mariadb:replication://10.4.4.20:3306,10.4.4.21:3306/cvim_db?characterEncoding=UTF-8&serverTimezone=Asia/Seoul&useServerPrepStmts=true&failoverEnable=true
-      jdbc-url: jdbc:mariadb://10.4.4.20:3306,10.4.4.21:3306/cvim_db?useServerPrepStmts=true&characterEncoding=UTF-8&serverTimezone=Asia/Seoul
+      #jdbc-url: jdbc:mariadb://10.4.4.20:3306,10.4.4.21:3306/cvim_db?useServerPrepStmts=true&characterEncoding=UTF-8&serverTimezone=Asia/Seoul
       # FOR MaxScale
       #jdbc-url: jdbc:mariadb://10.4.4.30:4006/cvim_db?characterEncoding=UTF-8&serverTimezone=Asia/Seoul&useServerPrepStmts=true
 

+ 14 - 0
evps-comm-server/src/main/resources/logback-spring-appender.xml

@@ -8,6 +8,20 @@
         </encoder>
     </appender>
 
+    <appender name="FILE_HEALTH" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <file>${LOG_PATH}${LOG_FILE_NAME_HEALTH}</file>
+        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
+            <charset>${FILE_LOG_CHARSET}</charset>
+            <pattern>${LOG_PATTERN_HEALTH}</pattern>
+            <immediateFlush>true</immediateFlush>
+        </encoder>
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+            <fileNamePattern>${LOG_BACKUP_PATH}${LOG_FILE_NAME_HEALTH}.${LOG_FILE_NAME_BACKUP}</fileNamePattern>
+            <maxFileSize>${MAX_FILESIZE}</maxFileSize>
+            <maxHistory>${MAX_HISTORY}</maxHistory>
+        </rollingPolicy>
+    </appender>
+
     <appender name="FILE_PACKET" class="ch.qos.logback.classic.sift.SiftingAppender">
         <discriminator>
             <key>id</key>

+ 15 - 2
evps-comm-server/src/main/resources/logback-spring.xml

@@ -2,7 +2,7 @@
 <configuration scan="true" scanPeriod="60 seconds">
     <shutdownHook class="ch.qos.logback.core.hook.DelayingShutdownHook"/>
 
-    <property name="APP_CLASS_PATH"  value="com.evps.comm.tester"/>
+    <property name="APP_CLASS_PATH"  value="com.evps.comm.server"/>
     <property name="PROJECT_PREFIX"  value="evps-comm"/>
     <property name="PROJECT_NAME"    value="${PROJECT_PREFIX}-server"/>
     <property name="ROOT_LOG_LEVEL"  value="INFO"/>
@@ -20,8 +20,9 @@
     <property name="LOG_FILE_NAME_PACKET"  value="${PROJECT_PREFIX}-packet"/>
     <property name="LOG_FILE_NAME_SESSION" value="${PROJECT_PREFIX}-session.log"/>
     <property name="LOG_FILE_NAME_KAFKA"   value="${PROJECT_PREFIX}-kafka.log"/>
+    <property name="LOG_FILE_NAME_HEALTH"  value="${PROJECT_PREFIX}-health.log"/>
 
-    <property name="MAX_FILESIZE" value="10MB"/>
+    <property name="MAX_FILESIZE" value="60MB"/>
     <property name="MAX_HISTORY"  value="10"/>
 
     <property name="LOG_PATTERN_FILE"        value="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %msg%n"/>
@@ -29,6 +30,7 @@
     <property name="LOG_PATTERN_PACKET"      value="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %msg%n"/>
     <property name="LOG_PATTERN_SESSION"     value="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %msg%n"/>
     <property name="LOG_PATTERN_KAFKA"       value="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %msg%n"/>
+    <property name="LOG_PATTERN_HEALTH"      value="[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%-5level] %msg%n"/>
     <property name="LOG_PATTERN_CONSOLE"     value="[%d{HH:mm:ss.SSS}] %highlight([%5level]): %cyan(%msg) %n"/>
 
     <springProfile name="!xxx">
@@ -48,6 +50,12 @@
             <appender-ref ref="FILE_ERROR"/>
         </root>
 
+        <logger name="${APP_CLASS_PATH}.health" level="INFO" additivity="false">
+            <appender-ref ref="CONSOLE"/>
+            <appender-ref ref="FILE_HEALTH"/>
+            <appender-ref ref="FILE_ERROR"/>
+        </logger>
+
         <logger name="${APP_CLASS_PATH}.kafka" level="INFO" additivity="false">
             <appender-ref ref="CONSOLE"/>
             <appender-ref ref="FILE_KAFKA"/>
@@ -77,6 +85,11 @@
             <appender-ref ref="FILE_ERROR"/>
         </root>
 
+        <logger name="${APP_CLASS_PATH}.health" level="INFO" additivity="false">
+            <appender-ref ref="FILE_HEALTH"/>
+            <appender-ref ref="FILE_ERROR"/>
+        </logger>
+
         <logger name="${APP_CLASS_PATH}.kafka" level="INFO" additivity="false">
             <appender-ref ref="FILE_KAFKA"/>
             <appender-ref ref="FILE_ERROR"/>