From 87cbef018e492e02ee727f26951ef86c5c5cbcb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?dhji=28=EC=A7=80=EB=8C=80=ED=95=9C=29?= Date: Mon, 11 Mar 2024 19:00:25 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20docker=20test=20=ED=99=98=EA=B2=BD=20?= =?UTF-8?q?=EA=B5=AC=EC=B6=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 현 구현한 것으로는 drone 데이터가 초당 100건 정도 수용할 수 있을 정도 테스트 환경은 macos m3 core 1개와 memory 512MB(jvm 123.75MB)를 활용 --- .gitignore | 2 ++ app/kac-app/Dockerfile | 5 ++- .../palnet/kac/app/config/AppReadyEvent.java | 31 +++++++++++++++++++ app/kac-socket-app/Dockerfile | 5 ++- .../command/impl/AdsbDroneCommandImpl.java | 3 +- .../command/impl/AntosDroneCommandImpl.java | 1 - .../command/impl/SandboxDroneCommandImpl.java | 7 ----- .../kac/socket/core/config/AppReadyEvent.java | 15 ++++++++- .../kac/socket/core/config/AsyncConfig.java | 10 +++--- .../kac/socket/core/storage/DroneStorage.java | 5 +-- .../kac/socket/service/KacAppService.java | 8 ++--- .../kac/socket/service/WebSocketService.java | 2 +- app/kac-websocket-app/Dockerfile | 5 ++- .../controller/SocketReceiverController.java | 1 - .../websocket/core/config/AppReadyEvent.java | 15 ++++++++- docker-compose.yml | 25 ++++++++++++--- http-client/http/ws.http | 3 ++ 17 files changed, 109 insertions(+), 34 deletions(-) create mode 100644 app/kac-app/src/main/java/kr/co/palnet/kac/app/config/AppReadyEvent.java diff --git a/.gitignore b/.gitignore index de2e635..8832db1 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,5 @@ out/ logs/ logs/** +### local ### +/.java-version diff --git a/app/kac-app/Dockerfile b/app/kac-app/Dockerfile index b629e52..dcb69df 100644 --- a/app/kac-app/Dockerfile +++ b/app/kac-app/Dockerfile @@ -1,9 +1,12 @@ FROM openjdk:21 ENV TZ=Asia/Seoul +#ENV JAVA_OPTS="-Xms512M -Xmx512M" +ENV JAVA_OPTS="" EXPOSE 8000 WORKDIR /app -ENTRYPOINT ["java","-jar","/app/kac-app-1.0.0.jar"] \ No newline at end of file +#ENTRYPOINT ["java","-jar","/app/kac-app-1.0.0.jar"] +CMD java $JAVA_OPTS -jar /app/kac-app-1.0.0.jar \ No newline at end of file diff --git a/app/kac-app/src/main/java/kr/co/palnet/kac/app/config/AppReadyEvent.java b/app/kac-app/src/main/java/kr/co/palnet/kac/app/config/AppReadyEvent.java new file mode 100644 index 0000000..fc5ba9f --- /dev/null +++ b/app/kac-app/src/main/java/kr/co/palnet/kac/app/config/AppReadyEvent.java @@ -0,0 +1,31 @@ +package kr.co.palnet.kac.app.config; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Component; + +import java.lang.management.ManagementFactory; +import java.lang.management.MemoryMXBean; +import java.lang.management.MemoryPoolMXBean; + +@Slf4j +@RequiredArgsConstructor +@Component +public class AppReadyEvent implements ApplicationListener { + + @Override + public void onApplicationEvent(ApplicationReadyEvent event) { + try { + float mb = 1024f * 1024f; + MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean(); + log.info("current heap memory init(xms): {}mb, max(xmx): {}mb", memoryBean.getHeapMemoryUsage().getInit() / mb, memoryBean.getHeapMemoryUsage().getMax() / mb); + for (MemoryPoolMXBean mp : ManagementFactory.getMemoryPoolMXBeans()) { + log.info("Pool: {} (type {}) = {}", mp.getName(), mp.getType(), mp.getUsage().getMax() / mb); + } + } catch (Exception e) { + log.warn("when start app, not read jvm heap memory information."); + } + } +} diff --git a/app/kac-socket-app/Dockerfile b/app/kac-socket-app/Dockerfile index 66eb404..7f27418 100644 --- a/app/kac-socket-app/Dockerfile +++ b/app/kac-socket-app/Dockerfile @@ -1,9 +1,12 @@ FROM openjdk:21 ENV TZ=Asia/Seoul +#ENV JAVA_OPTS="-Xms512M -Xmx512M" +ENV JAVA_OPTS="" EXPOSE 8003 WORKDIR /app -ENTRYPOINT ["java","-jar","/app/kac-socket-app-1.0.0.jar"] \ No newline at end of file +#ENTRYPOINT ["java",${JAVA_OPTS},"-jar","/app/kac-socket-app-1.0.0.jar"] +CMD java $JAVA_OPTS -jar /app/kac-socket-app-1.0.0.jar \ No newline at end of file diff --git a/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/command/impl/AdsbDroneCommandImpl.java b/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/command/impl/AdsbDroneCommandImpl.java index d185671..225aaca 100644 --- a/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/command/impl/AdsbDroneCommandImpl.java +++ b/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/command/impl/AdsbDroneCommandImpl.java @@ -115,6 +115,7 @@ public class AdsbDroneCommandImpl implements DroneCommand { droneCacheStorage.put(drone.getObjectId(), drone); } + // STEP 2. 이력 생성할 전문 전달 -> DRON의 대한 식별정보만 이력 관리 try { // 저장 해 놓았다가 한거번에 전송 - 필요한 곳에 전송(HISTORY, UTM) @@ -128,7 +129,7 @@ public class AdsbDroneCommandImpl implements DroneCommand { try { if ("PA".equals(drone.getObjectId().substring(0, 2))) { - webSocketService.sendData(drone); + webSocketService.asyncSendData(drone); } } catch (Exception e) { log.error("ERROR : {}", e.getMessage(), e); diff --git a/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/command/impl/AntosDroneCommandImpl.java b/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/command/impl/AntosDroneCommandImpl.java index 3515f07..1d8163e 100644 --- a/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/command/impl/AntosDroneCommandImpl.java +++ b/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/command/impl/AntosDroneCommandImpl.java @@ -129,7 +129,6 @@ public class AntosDroneCommandImpl implements DroneCommand { // STEP 3. 화면에 표출할 정보 WebSocket 전달 try { if ("PA".equals(drone.getObjectId().substring(0, 2))) { -// webSocketService.sendData(drone); webSocketService.asyncSendData(drone); } } catch (Exception e) { diff --git a/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/command/impl/SandboxDroneCommandImpl.java b/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/command/impl/SandboxDroneCommandImpl.java index 01dfb53..b628e2a 100644 --- a/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/command/impl/SandboxDroneCommandImpl.java +++ b/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/command/impl/SandboxDroneCommandImpl.java @@ -120,24 +120,17 @@ public class SandboxDroneCommandImpl implements DroneCommand { droneCacheStorage.put(drone.getObjectId(), drone); } - // STEP 2. 이력 생성할 전문 전달 -> DRON의 대한 식별정보만 이력 관리 try { - -// kacAppService.sendData(drone); -// kacAppService.asyncSendData(drone); - // 저장 해 놓았다가 한거번에 전송 - 필요한 곳에 전송(HISTORY, UTM) DroneStorage droneStorage = DroneStorage.getInstance(); droneStorage.add(drone); - } catch (Exception e) { log.error("ERROR : {}", e.getMessage(), e); } // STEP 3. 화면에 표출할 정보 WebSocket 전달 try { -// webSocketService.sendData(drone); webSocketService.asyncSendData(drone); } catch (Exception e) { log.error("ERROR : {}", e.getMessage(), e); diff --git a/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/config/AppReadyEvent.java b/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/config/AppReadyEvent.java index 4204565..8ab7346 100644 --- a/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/config/AppReadyEvent.java +++ b/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/config/AppReadyEvent.java @@ -7,6 +7,10 @@ import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.context.ApplicationListener; import org.springframework.stereotype.Component; +import java.lang.management.ManagementFactory; +import java.lang.management.MemoryMXBean; +import java.lang.management.MemoryPoolMXBean; + @Slf4j @RequiredArgsConstructor @Component @@ -16,7 +20,16 @@ public class AppReadyEvent implements ApplicationListener @Override public void onApplicationEvent(ApplicationReadyEvent event) { - log.debug(">>>> onApplicationEvent <<<<<"); + try { + float mb = 1024f * 1024f; + MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean(); + log.info("current heap memory init(xms): {}mb, max(xmx): {}mb", memoryBean.getHeapMemoryUsage().getInit() / mb, memoryBean.getHeapMemoryUsage().getMax() / mb); + for (MemoryPoolMXBean mp : ManagementFactory.getMemoryPoolMXBeans()) { + log.info("Pool: {} (type {}) = {}", mp.getName(), mp.getType(), mp.getUsage().getMax() / mb); + } + } catch (Exception e) { + log.warn("when start app, not read jvm heap memory information."); + } socketServer.start(); } } diff --git a/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/config/AsyncConfig.java b/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/config/AsyncConfig.java index 7e2129a..af0e54d 100644 --- a/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/config/AsyncConfig.java +++ b/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/config/AsyncConfig.java @@ -17,9 +17,9 @@ public class AsyncConfig implements AsyncConfigurer { @Override public Executor getAsyncExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); - executor.setCorePoolSize(10); - executor.setMaxPoolSize(50); - executor.setQueueCapacity(100); + executor.setCorePoolSize(20); + executor.setMaxPoolSize(100); + executor.setQueueCapacity(500); executor.setThreadNamePrefix("th-async-default-"); executor.initialize(); return executor; @@ -34,8 +34,8 @@ public class AsyncConfig implements AsyncConfigurer { public Executor restClientThreadPoolTaskExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(10); - executor.setMaxPoolSize(100); - executor.setQueueCapacity(500); + executor.setMaxPoolSize(1000); + executor.setQueueCapacity(1000); executor.setThreadNamePrefix("th-async-rc-"); executor.initialize(); return executor; diff --git a/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/storage/DroneStorage.java b/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/storage/DroneStorage.java index 54f0901..8331326 100644 --- a/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/storage/DroneStorage.java +++ b/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/storage/DroneStorage.java @@ -82,9 +82,10 @@ public class DroneStorage { Instant compareTime = Instant.now().minusSeconds(60); // 마지막 데이터가 1분 이상된 데이터라면 삭제 - DroneDto lastDronDto = list.stream().toList().getLast(); + DroneDto lastDroneDto = list.stream().toList().getLast(); +// DroneDto lastDroneDto = list.stream().toList().get(list.size() - 1); - if ((lastDronDto.isSendHistroy() && lastDronDto.isSendUtm()) || compareTime.isAfter(lastDronDto.getRegDt())) { + if ((lastDroneDto.isSendHistroy() && lastDroneDto.isSendUtm()) || compareTime.isAfter(lastDroneDto.getRegDt())) { // list.remove(lastDronDto); droneMap.remove(objectId); continue; diff --git a/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/service/KacAppService.java b/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/service/KacAppService.java index dc51011..bda08f6 100644 --- a/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/service/KacAppService.java +++ b/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/service/KacAppService.java @@ -7,7 +7,6 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpStatus; -import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; @@ -58,7 +57,7 @@ public class KacAppService { sendData(dto); } - public boolean sendDataAll(Map> history){ + public boolean sendDataAll(Map> history) { RestClient client = getRestClient(); ResponseEntity resp = client.post() .uri(SEND_HISTORY_ALL) @@ -66,10 +65,7 @@ public class KacAppService { .body(history) .retrieve() .toBodilessEntity(); - if(resp.getStatusCode() == HttpStatus.OK){ - return true; - } - return false; + return resp.getStatusCode() == HttpStatus.OK; } private RestClient getRestClient() { diff --git a/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/service/WebSocketService.java b/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/service/WebSocketService.java index 618b135..89f104e 100644 --- a/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/service/WebSocketService.java +++ b/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/service/WebSocketService.java @@ -36,7 +36,7 @@ public class WebSocketService { .toBodilessEntity(); } - @Async + @Async("restClientThreadPoolTaskExecutor") public void asyncSendData(DroneDto dto) { sendData(dto); } diff --git a/app/kac-websocket-app/Dockerfile b/app/kac-websocket-app/Dockerfile index bf4789c..3a58906 100644 --- a/app/kac-websocket-app/Dockerfile +++ b/app/kac-websocket-app/Dockerfile @@ -1,10 +1,13 @@ FROM openjdk:21 ENV TZ=Asia/Seoul +#ENV JAVA_OPTS="-Xms512M -Xmx512M" +ENV JAVA_OPTS="" EXPOSE 8001 EXPOSE 8002 WORKDIR /app -ENTRYPOINT ["java","-jar","/app/kac-websocket-app-1.0.0.jar"] \ No newline at end of file +#ENTRYPOINT ["java","-jar","/app/kac-websocket-app-1.0.0.jar"] +CMD java $JAVA_OPTS -jar /app/kac-websocket-app-1.0.0.jar \ No newline at end of file diff --git a/app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/controller/SocketReceiverController.java b/app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/controller/SocketReceiverController.java index 6663d24..003e204 100644 --- a/app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/controller/SocketReceiverController.java +++ b/app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/controller/SocketReceiverController.java @@ -24,7 +24,6 @@ public class SocketReceiverController { @PostMapping("/drone") public ResponseEntity receiver(@RequestBody DroneDto droneDto) { log.debug("websocket message receiver : {}", droneDto); - DroneControlDto history = controlService.dronDtoToControlDtoConvert(droneDto); // DRON의 대한 식별정보만 이력 관리 diff --git a/app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/core/config/AppReadyEvent.java b/app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/core/config/AppReadyEvent.java index be2567c..7338ddf 100644 --- a/app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/core/config/AppReadyEvent.java +++ b/app/kac-websocket-app/src/main/java/kr/co/palnet/kac/websocket/core/config/AppReadyEvent.java @@ -7,6 +7,10 @@ import org.springframework.boot.context.event.ApplicationReadyEvent; import org.springframework.context.ApplicationListener; import org.springframework.stereotype.Component; +import java.lang.management.ManagementFactory; +import java.lang.management.MemoryMXBean; +import java.lang.management.MemoryPoolMXBean; + @Slf4j @RequiredArgsConstructor @Component @@ -16,7 +20,16 @@ public class AppReadyEvent implements ApplicationListener @Override public void onApplicationEvent(ApplicationReadyEvent event) { - log.debug(">>>> onApplicationEvent <<<<<"); + try { + float mb = 1024f * 1024f; + MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean(); + log.info("current heap memory init(xms): {}mb, max(xmx): {}mb", memoryBean.getHeapMemoryUsage().getInit() / mb, memoryBean.getHeapMemoryUsage().getMax() / mb); + for (MemoryPoolMXBean mp : ManagementFactory.getMemoryPoolMXBeans()) { + log.info("Pool: {} (type {}) = {}", mp.getName(), mp.getType(), mp.getUsage().getMax() / mb); + } + } catch (Exception e) { + log.warn("when start app, not read jvm heap memory information."); + } socketServer.start(); } } diff --git a/docker-compose.yml b/docker-compose.yml index d95a25f..97173e7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -33,13 +33,18 @@ services: - pav_kac_networks volumes: - ./app/kac-app/build/libs:/app + deploy: + resources: + limits: + cpus: "1.0" + memory: 512M - kac-socket: + kac-socket-app: build: context: ./app/kac-socket-app dockerfile: Dockerfile - depends_on: - - database +# depends_on: +# - database ports: - 18003:8003 container_name: kac-socket-app @@ -49,13 +54,18 @@ services: - pav_kac_networks volumes: - ./app/kac-socket-app/build/libs:/app + deploy: + resources: + limits: + cpus: "1.0" + memory: 512M kac-websocket-app: build: context: ./app/kac-websocket-app dockerfile: Dockerfile - depends_on: - - database +# depends_on: +# - database ports: - 18001:8001 - 18002:8002 @@ -66,6 +76,11 @@ services: - pav_kac_networks volumes: - ./app/kac-websocket-app/build/libs:/app + deploy: + resources: + limits: + cpus: "1.0" + memory: 512M networks: #네트워크 설정 pav_kac_networks: \ No newline at end of file diff --git a/http-client/http/ws.http b/http-client/http/ws.http index 08f7141..ea9cb57 100644 --- a/http-client/http/ws.http +++ b/http-client/http/ws.http @@ -10,6 +10,9 @@ WEBSOCKET {{wsHost}}/ws WEBSOCKET {{wsHost}}/ws +### docker websocket +WEBSOCKET ws://localhost:18001/ws + ### 기존 websocket WEBSOCKET ws://localhost:8081/ws #Content-Type: application-json