From 32b003ec24f73bbe14d8b071ad200c0fcf113850 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?dhji=28=EC=A7=80=EB=8C=80=ED=95=9C=29?= Date: Sat, 9 Mar 2024 00:11:06 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20cache=EB=A1=9C=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=ED=95=98=EB=8A=94=20DroneStorage=EC=9D=98=20=EC=9E=98=EB=AA=BB?= =?UTF-8?q?=EB=90=9C=20=EC=B0=B8=EC=A1=B0=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 참조하는 객체에 의하여 무한증식하는 현상 수정 --- .../src/main/resources/application.yml | 48 +++++++++---- .../command/impl/SandboxDroneCommandImpl.java | 4 +- .../kac/socket/core/storage/DroneStorage.java | 50 ++++++++----- .../kac/socket/service/ScheduledService.java | 72 ++++++++++--------- .../src/main/resources/application.yml | 3 + socket-test/pav-100-dron.js | 6 +- 6 files changed, 114 insertions(+), 69 deletions(-) diff --git a/app/kac-app/src/main/resources/application.yml b/app/kac-app/src/main/resources/application.yml index 0492219..4454c06 100644 --- a/app/kac-app/src/main/resources/application.yml +++ b/app/kac-app/src/main/resources/application.yml @@ -12,6 +12,28 @@ server.port: 8000 logging: level: kr.co.palnet: DEBUG +# jdbc: +# audit: OFF +# resultset: OFF +# resultsettable: INFO #SQL 결과 데이터 Table을 로그로 남긴다. +# sqlonly: OFF #SQL만 로그로 남긴다. +# sqltiming: info #SQL과 소요시간을 표기한다. +# connection : trace # 커넥션 확인가능 +# org.hibernate: +# SQL: off +# type.descriptor.sql.BasicBinder: TRACE +# com.zaxxer.hikari.HikariConfig: DEBUG +# com.zaxxer.hikari: TRACE +# file: +# name: ./logs/kac-app/data.log +# logback: +# rollingpolicy: +# clean-history-on-start: false +# # file-name-pattern: ${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz +# file-name-pattern: ${LOG_FILE}.%d{yyyy-MM-dd}.%i.log +# max-file-size: 10MB +# max-history: 60 +# total-size-cap: 100MB management: endpoints: @@ -28,19 +50,19 @@ spring: logging: level: - kr.co.palnet: DEBUG - jdbc: - audit: OFF - resultset: OFF - resultsettable: INFO #SQL 결과 데이터 Table을 로그로 남긴다. - sqlonly: OFF #SQL만 로그로 남긴다. - sqltiming: info #SQL과 소요시간을 표기한다. - connection : trace # 커넥션 확인가능 - org.hibernate: - SQL: off - type.descriptor.sql.BasicBinder: TRACE - com.zaxxer.hikari.HikariConfig: DEBUG - com.zaxxer.hikari: TRACE + kr.co.palnet: info + jdbc: off +# audit: OFF +# resultset: OFF +# resultsettable: INFO #SQL 결과 데이터 Table을 로그로 남긴다. +# sqlonly: OFF #SQL만 로그로 남긴다. +# sqltiming: info #SQL과 소요시간을 표기한다. +# connection : trace # 커넥션 확인가능 + org.hibernate: off +# SQL: off +# type.descriptor.sql.BasicBinder: TRACE +# com.zaxxer.hikari.HikariConfig: off + com.zaxxer.hikari: off file: name: ./logs/kac-app/data.log logback: 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 061eaf0..01dfb53 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 @@ -128,8 +128,8 @@ public class SandboxDroneCommandImpl implements DroneCommand { // kacAppService.asyncSendData(drone); // 저장 해 놓았다가 한거번에 전송 - 필요한 곳에 전송(HISTORY, UTM) - DroneStorage dronStorage = DroneStorage.getInstance(); - dronStorage.add(drone); + DroneStorage droneStorage = DroneStorage.getInstance(); + droneStorage.add(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/storage/DroneStorage.java b/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/storage/DroneStorage.java index 14d0930..54f0901 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 @@ -51,34 +51,42 @@ public class DroneStorage { return; } - List list = droneMap.get(drone.getObjectId()); + List list = this.droneMap.get(drone.getObjectId()); if (list == null) { list = new ArrayList<>(); +// list = new CopyOnWriteArrayList<>(); +// list = new ConcurrentLinkedQueue<>(); +// droneMap.put(drone.getObjectId(), list); } +// log.info("add :: {}::{}::{}", drone.getObjectId(), droneMap.keySet().size(), list.size()); list.add(drone); - droneMap.put(drone.getObjectId(), list); + this.droneMap.put(drone.getObjectId(), list); +// list.offer(drone); + if ("PA-DRON-004-000".equals(drone.getObjectId())) + log.info("add :: {}::{}::{}", drone.getObjectId(), droneMap.keySet().size(), list.size()); } // 1분 이상된 데이터 삭제 또는 처리가 끝난 데이터 삭제 public void removeByCondition() { - for (String key : droneMap.keySet()) { - List list = droneMap.get(key); + for (String objectId : droneMap.keySet()) { + List list = droneMap.get(objectId); if (list == null) { continue; } else if (list.isEmpty()) { - droneMap.remove(key); + droneMap.remove(objectId); continue; } - // 1분 전 시간 Instant compareTime = Instant.now().minusSeconds(60); // 마지막 데이터가 1분 이상된 데이터라면 삭제 - DroneDto lastDronDto = list.getLast(); + DroneDto lastDronDto = list.stream().toList().getLast(); + if ((lastDronDto.isSendHistroy() && lastDronDto.isSendUtm()) || compareTime.isAfter(lastDronDto.getRegDt())) { - list.remove(lastDronDto); +// list.remove(lastDronDto); + droneMap.remove(objectId); continue; } @@ -89,11 +97,18 @@ public class DroneStorage { public List getAllByUtm() { // 보내지 않은 모든 데이터 추출 - return droneMap.values().stream().reduce((list, result) -> { - List yetSendData = list.stream().filter(droneDto -> !droneDto.isSendUtm()).toList(); - result.addAll(yetSendData); - return result; - }).orElse(new ArrayList<>()); +// return droneMap.values().stream().reduce((list, result) -> { +// log.info("list: {}, result: {}",list, result); +// List yetSendData = list.stream().filter(droneDto -> !droneDto.isSendUtm()).toList(); +// result.addAll(yetSendData); +// return result; +// }).orElse(new ArrayList<>()); + List resultList = new ArrayList<>(); + droneMap.values().forEach(droneDtoList -> { + List list = droneDtoList.stream().filter(droneDto -> !droneDto.isSendUtm()).toList(); + resultList.addAll(list); + }); + return resultList; } // public List getAllByHistory() { @@ -110,9 +125,12 @@ public class DroneStorage { Map> sendList = new HashMap<>(); for (String objectId : droneMap.keySet()) { List droneDtoList = droneMap.get(objectId); - List list = droneDtoList.stream().filter(droneDto -> !droneDto.isSendHistroy()).toList(); - if (list != null && !list.isEmpty()) { - sendList.put(objectId, list); + if (droneDtoList != null) { +// ConcurrentLinkedQueue list = droneDtoList.stream().filter(droneDto -> !droneDto.isSendHistroy()).collect(Collectors.toCollection(ConcurrentLinkedQueue::new)); + List list = droneDtoList.stream().filter(droneDto -> !droneDto.isSendHistroy()).toList(); + if (!list.isEmpty()) { + sendList.put(objectId, list); + } } } return sendList; diff --git a/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/service/ScheduledService.java b/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/service/ScheduledService.java index 118eaf3..a1acc5f 100644 --- a/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/service/ScheduledService.java +++ b/app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/service/ScheduledService.java @@ -11,7 +11,6 @@ import org.springframework.stereotype.Service; import java.time.Instant; import java.time.ZoneId; import java.time.format.DateTimeFormatter; -import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -26,13 +25,18 @@ public class ScheduledService { @Scheduled(fixedDelay = 2 * 1000) public void sendDataByHistory() { + DroneStorage droneStorage = DroneStorage.getInstance(); Map> history = droneStorage.getAllByHistory(); + log.info("sendDataByHistory size : {}", history.keySet().size()); + // list 합 + history.values().stream().map(List::size).reduce(Integer::sum).ifPresent(s -> log.info("list size sum : {}", s)); if (!history.isEmpty()) { if (kacAppService.sendDataAll(history)) { history.values().forEach(droneDtoList -> droneDtoList.forEach(droneDto -> droneDto.setSendHistroy(true))); } + history.values().forEach(droneDtoList -> droneDtoList.forEach(droneDto -> droneDto.setSendHistroy(true))); } } @@ -44,58 +48,56 @@ public class ScheduledService { DroneStorage droneStorage = DroneStorage.getInstance(); List list = droneStorage.getAllByUtm(); - // 가공 - List droneInfoList = list.stream().map(model -> { - UtmDto.DroneInfo droneInfo = UtmDto.DroneInfo.builder() - .id(model.getObjectId()) - .latitude(model.getLat().toString()) - .longitude(model.getLon().toString()) - .height(model.getElev().toString()) - .build(); - return droneInfo; - }).collect(Collectors.toList()); + try { - if (droneInfoList.isEmpty()) return; + List droneInfoList = list.stream().map(model -> { + UtmDto.DroneInfo droneInfo = UtmDto.DroneInfo.builder() + .id(model.getObjectId()) + .latitude(model.getLat().toString()) + .longitude(model.getLon().toString()) + .height(model.getElev().toString()) + .build(); + return droneInfo; + }).collect(Collectors.toList()); + // 가공 - DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss") - .withZone(ZoneId.of("Asia/Seoul")); - String dateStr = formatter.format(Instant.now()); + if (droneInfoList.isEmpty()) return; - UtmDto utmDto = UtmDto.builder() - .GPSime(dateStr) - .droneInfo(droneInfoList) - .build(); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss") + .withZone(ZoneId.of("Asia/Seoul")); + String dateStr = formatter.format(Instant.now()); + + UtmDto utmDto = UtmDto.builder() + .GPSime(dateStr) + .droneInfo(droneInfoList) + .build(); // if (externalService.sendDataToUtm(utmDto)) { // list.forEach(drone -> drone.setSendUtm(true)); // } - // TODO 현재 통신이 안되므로 모두 보낸다는 가정으로 진행 - list.forEach(drone -> drone.setSendUtm(true)); + // TODO 현재 통신이 안되므로 모두 보낸다는 가정으로 진행 + list.forEach(drone -> drone.setSendUtm(true)); + } catch (Exception e) { + log.error("ERROR : {}", e.getMessage(), e); + if (list != null) { + log.warn("list : {}", list.size()); + } else { + log.warn("list is null"); + } + } } // 사용을 다한 데이터 제거 - @Scheduled(fixedDelay = 1000 * 30) + @Scheduled(fixedDelay = 30 * 1000) public void removeDrone() { - log.debug(">>>> removeDrone <<<<<"); + log.info(">>>> removeDrone <<<<<"); DroneStorage droneStorage = DroneStorage.getInstance(); Map> all = droneStorage.getAll(); - if (all != null) { - log.debug(">>>> remove drone before size : {}::{}", all.keySet().size(), all.values().stream().reduce((list, result) -> { - result.addAll(list); - return result; - }).orElse(new ArrayList<>()).size()); - } droneStorage.removeByCondition(); - if (all != null) { - log.debug(">>>> remove drone before size : {}::{}", all.keySet().size(), all.values().stream().reduce((list, result) -> { - result.addAll(list); - return result; - }).orElse(new ArrayList<>()).size()); - } } diff --git a/app/kac-socket-app/src/main/resources/application.yml b/app/kac-socket-app/src/main/resources/application.yml index 5f8b307..9f3b94f 100644 --- a/app/kac-socket-app/src/main/resources/application.yml +++ b/app/kac-socket-app/src/main/resources/application.yml @@ -33,6 +33,9 @@ spring: activate: on-profile: local +logging: + level: + kr.co.palnet: info --- diff --git a/socket-test/pav-100-dron.js b/socket-test/pav-100-dron.js index c709c61..429c713 100644 --- a/socket-test/pav-100-dron.js +++ b/socket-test/pav-100-dron.js @@ -2,8 +2,8 @@ const { getConnection, writeData } = require('./pav-client'); const { dumyData } = require('./pav-utils'); const host = "localhost" -// const port = 8003; -const port = 18003; +const port = 8003; +// const port = 18003; const prefix = 'PA-DRON-004-'; const severalDrones = cnt => { @@ -56,7 +56,7 @@ const severalDrones = cnt => { return clients; }; // -const clients = severalDrones(10); +const clients = severalDrones(100); const dist = 0.01; const sendData = cnt => { const direction = Math.floor(cnt / 10) % 4;