ApplicationLifecycle.java 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. package com.tsi.comm.server;
  2. import com.tsi.comm.server.config.ApplicationConfig;
  3. import com.tsi.comm.server.config.TsiCvimServerConfig;
  4. import com.tsi.comm.server.kafka.KafkaConsumerService;
  5. import com.tsi.comm.server.kafka.KafkaProducerService;
  6. import com.tsi.comm.server.process.dbms.TsiCvimDbmsProcess;
  7. import com.tsi.comm.server.process.logging.TsiCvimLoggingProcess;
  8. import com.tsi.comm.server.process.packet.TsiCvimPacketProcess;
  9. import com.tsi.comm.server.repository.ApplicationRepository;
  10. import com.tsi.comm.server.service.TsiCommServerService;
  11. import com.tsi.comm.server.tcp.TsiCvimServer;
  12. import com.tsi.comm.server.vo.TsiAlarmConfigVo;
  13. import com.tsi.comm.server.vo.mariadb.AbstractDbmsVo;
  14. import com.tsi.comm.server.vo.mariadb.AlarmOccrVo;
  15. import lombok.RequiredArgsConstructor;
  16. import lombok.extern.slf4j.Slf4j;
  17. import javax.annotation.PostConstruct;
  18. import javax.annotation.PreDestroy;
  19. import java.text.SimpleDateFormat;
  20. import java.util.Date;
  21. @Slf4j
  22. @RequiredArgsConstructor
  23. //@Component
  24. public class ApplicationLifecycle {
  25. private final ApplicationConfig applicationConfig;
  26. private final TsiCvimServerConfig serverConfig;
  27. private final TsiCommServerService tsiCommServerService;
  28. private final KafkaConsumerService kafkaConsumerService;
  29. private final KafkaProducerService kafkaProducerService;
  30. private final TsiCvimPacketProcess packetProcess;
  31. private final TsiCvimLoggingProcess loggingProcess;
  32. private final TsiCvimDbmsProcess dbmsProcess;
  33. private final TsiCvimServer cvimServer;
  34. private String applicationName;
  35. private int serverId = 0;
  36. @PostConstruct
  37. public void start() {
  38. SimpleDateFormat sdfDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  39. log.info("");
  40. log.info("************************************************************************************");
  41. log.info("** TSI CVIM System **");
  42. log.info("** CVIM Communication Server Program. **");
  43. log.info("** [ver.1.0] **");
  44. log.info("** startup: {}", sdfDate.format(new Date()));
  45. log.info("************************************************************************************");
  46. this.applicationConfig.setStartSchedule(false);
  47. serverId = this.serverConfig.getServerId();
  48. this.applicationName = TsiCommServerApplication.APPLICATION_NAME + "-" + this.serverConfig.getServerId();
  49. ApplicationRepository.processStateVo.setProcessId(applicationName);
  50. this.tsiCommServerService.init();
  51. this.kafkaConsumerService.start();
  52. this.kafkaProducerService.start();
  53. this.packetProcess.start();
  54. this.loggingProcess.start();
  55. this.dbmsProcess.start();
  56. // Netty 서버 시작은 백그라운드 스레드에서 실행되므로, 이 메서드를 블로킹하지 않습니다.
  57. this.cvimServer.run();
  58. this.serverConfig.setStartup(true);
  59. try {
  60. // 시스템 시작 알람 이력 저장
  61. AlarmOccrVo alarm = new AlarmOccrVo(AbstractDbmsVo.DBMS_ALARM_OCCR_HS);
  62. alarm.setAlarmCode(TsiAlarmConfigVo.SYS_00);
  63. alarm.setAlarmTarget(applicationName);
  64. alarm.setAlarmValue("Running");
  65. this.tsiCommServerService.insertAlarmOccrHs(alarm);
  66. this.tsiCommServerService.updateProcessState(0);
  67. } catch(Exception e) {
  68. log.error("Error during startup alarm logging: {}", e.getMessage());
  69. }
  70. this.applicationConfig.setStartSchedule(true);
  71. log.info("Application has been started successfully.");
  72. }
  73. /**
  74. * Spring 컨텍스트가 종료될 때, 빈이 소멸되기 직전에 호출됩니다.
  75. */
  76. @PreDestroy
  77. public void stop() {
  78. SimpleDateFormat sdfDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  79. log.error("************************************************************************************");
  80. log.error("** Application Terminating: {}", sdfDate.format(new Date()));
  81. // 종료는 생성의 역순이 안전합니다.
  82. // 1. 새로운 연결을 막습니다.
  83. if (this.cvimServer != null) {
  84. this.cvimServer.stop();
  85. log.info("Netty Server stopped.");
  86. }
  87. if (this.kafkaConsumerService != null) {
  88. this.kafkaConsumerService.shutdown();
  89. log.info("Kafka Consumer stopped.");
  90. }
  91. // 2. 내부 처리 로직(워커 스레드 풀)을 종료합니다.
  92. if (this.packetProcess != null) {
  93. this.packetProcess.stop();
  94. log.info("Packet Process stopped.");
  95. }
  96. if (this.loggingProcess != null) {
  97. this.loggingProcess.stop();
  98. log.info("Logging Process stopped.");
  99. }
  100. if (this.dbmsProcess != null) {
  101. this.dbmsProcess.stop();
  102. log.info("DBMS Process stopped.");
  103. }
  104. // 3. 외부로 나가는 통신(Kafka Producer)을 종료합니다.
  105. if (this.kafkaProducerService != null) {
  106. this.kafkaProducerService.shutdown();
  107. log.info("Kafka Producer stopped.");
  108. }
  109. // 4. DB에 최종 상태를 기록합니다.
  110. if (this.tsiCommServerService != null) {
  111. this.serverConfig.setStartup(false);
  112. int serverId = this.serverConfig.getServerId();
  113. this.tsiCommServerService.updateNodeStatusTerm(serverId);
  114. // ... 시스템 종료 알람 저장 로직 ...
  115. this.tsiCommServerService.updateProcessState(2);
  116. log.info("Final DB states updated.");
  117. }
  118. log.error("************************************************************************************");
  119. }
  120. }