Browse Source

fix: cache로 사용하는 DroneStorage의 잘못된 참조 수정

- 참조하는 객체에 의하여 무한증식하는 현상 수정
feature/socket
지대한 7 months ago
parent
commit
32b003ec24
  1. 48
      app/kac-app/src/main/resources/application.yml
  2. 4
      app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/command/impl/SandboxDroneCommandImpl.java
  3. 50
      app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/core/storage/DroneStorage.java
  4. 72
      app/kac-socket-app/src/main/java/kr/co/palnet/kac/socket/service/ScheduledService.java
  5. 3
      app/kac-socket-app/src/main/resources/application.yml
  6. 6
      socket-test/pav-100-dron.js

48
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:

4
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);

50
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<DroneDto> list = droneMap.get(drone.getObjectId());
List<DroneDto> 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<DroneDto> list = droneMap.get(key);
for (String objectId : droneMap.keySet()) {
List<DroneDto> 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<DroneDto> getAllByUtm() {
// 보내지 않은 모든 데이터 추출
return droneMap.values().stream().reduce((list, result) -> {
List<DroneDto> 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<DroneDto> yetSendData = list.stream().filter(droneDto -> !droneDto.isSendUtm()).toList();
// result.addAll(yetSendData);
// return result;
// }).orElse(new ArrayList<>());
List<DroneDto> resultList = new ArrayList<>();
droneMap.values().forEach(droneDtoList -> {
List<DroneDto> list = droneDtoList.stream().filter(droneDto -> !droneDto.isSendUtm()).toList();
resultList.addAll(list);
});
return resultList;
}
// public List<DroneDto> getAllByHistory() {
@ -110,9 +125,12 @@ public class DroneStorage {
Map<String, List<DroneDto>> sendList = new HashMap<>();
for (String objectId : droneMap.keySet()) {
List<DroneDto> droneDtoList = droneMap.get(objectId);
List<DroneDto> list = droneDtoList.stream().filter(droneDto -> !droneDto.isSendHistroy()).toList();
if (list != null && !list.isEmpty()) {
sendList.put(objectId, list);
if (droneDtoList != null) {
// ConcurrentLinkedQueue<DroneDto> list = droneDtoList.stream().filter(droneDto -> !droneDto.isSendHistroy()).collect(Collectors.toCollection(ConcurrentLinkedQueue::new));
List<DroneDto> list = droneDtoList.stream().filter(droneDto -> !droneDto.isSendHistroy()).toList();
if (!list.isEmpty()) {
sendList.put(objectId, list);
}
}
}
return sendList;

72
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<String, List<DroneDto>> 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<DroneDto> list = droneStorage.getAllByUtm();
// 가공
List<UtmDto.DroneInfo> 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<UtmDto.DroneInfo> 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<String, List<DroneDto>> 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());
}
}

3
app/kac-socket-app/src/main/resources/application.yml

@ -33,6 +33,9 @@ spring:
activate:
on-profile: local
logging:
level:
kr.co.palnet: info
---

6
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;

Loading…
Cancel
Save