338 lines
12 KiB
YAML
338 lines
12 KiB
YAML
server:
|
||
port: 18090
|
||
tomcat:
|
||
threads:
|
||
max: 200
|
||
min-spare: 10
|
||
connection-timeout: 60000 # 60초로 증가
|
||
max-http-form-post-size: 50MB # 50MB로 증가
|
||
max-swallow-size: 50MB # 50MB로 증가
|
||
max-connections: 10000 # 최대 연결 수
|
||
accept-count: 100 # 대기열 크기
|
||
|
||
spring:
|
||
datasource:
|
||
# 원격 수집 DB
|
||
collect:
|
||
jdbc-url: jdbc:postgresql://211.208.115.83:5432/snpdb?currentSchema=signal&options=-csearch_path=signal,public&assumeMinServerVersion=12&reWriteBatchedInserts=true
|
||
username: snp
|
||
password: snp#8932
|
||
driver-class-name: org.postgresql.Driver
|
||
hikari:
|
||
pool-name: CollectHikariPool
|
||
connection-timeout: 30000 # 원격 연결이므로 타임아웃 증가
|
||
idle-timeout: 600000
|
||
max-lifetime: 1800000
|
||
maximum-pool-size: 80 # 20 -> 80 (총 250 중 32%, 배치 Reader 주 사용)
|
||
minimum-idle: 15 # 5 -> 15
|
||
# 원격 연결 안정성을 위한 추가 설정
|
||
connection-test-query: SELECT 1
|
||
validation-timeout: 5000
|
||
leak-detection-threshold: 60000 # 커넥션 누수 감지 (60초)
|
||
connection-init-sql: "SET TIME ZONE 'Asia/Seoul'; SET search_path TO signal, public;"
|
||
|
||
# 원격 조회 DB
|
||
query:
|
||
jdbc-url: jdbc:postgresql://211.208.115.83:5432/snpdb?currentSchema=signal&options=-csearch_path=signal,public&assumeMinServerVersion=12&reWriteBatchedInserts=true
|
||
username: snp
|
||
password: snp#8932
|
||
driver-class-name: org.postgresql.Driver
|
||
hikari:
|
||
pool-name: QueryHikariPool
|
||
connection-timeout: 5000
|
||
idle-timeout: 600000
|
||
max-lifetime: 1800000
|
||
maximum-pool-size: 180 # 120 -> 180 (WebSocket 대기열 + REST API 주 사용)
|
||
minimum-idle: 30 # 20 -> 30
|
||
connection-test-query: SELECT 1
|
||
validation-timeout: 5000
|
||
leak-detection-threshold: 60000 # 커넥션 누수 감지 (60초)
|
||
# PostGIS 함수를 위해 public 스키마를 search_path에 명시적으로 추가
|
||
connection-init-sql: "SET TIME ZONE 'Asia/Seoul'; SET search_path TO signal, public, pg_catalog; SET work_mem = '256MB'; SET synchronous_commit = 'off';"
|
||
statement-cache-size: 250
|
||
data-source-properties:
|
||
prepareThreshold: 3
|
||
preparedStatementCacheQueries: 250
|
||
|
||
# 로컬 배치 메타 DB (signal 스키마 사용)
|
||
batch:
|
||
jdbc-url: jdbc:postgresql://211.208.115.83:5432/snpdb?currentSchema=public&assumeMinServerVersion=12&reWriteBatchedInserts=true
|
||
username: snp
|
||
password: snp#8932
|
||
driver-class-name: org.postgresql.Driver
|
||
hikari:
|
||
pool-name: BatchHikariPool
|
||
maximum-pool-size: 30 # 20 -> 30 (총 250 중 12%, Spring Batch 메타데이터)
|
||
minimum-idle: 5 # 10 -> 5 (메타데이터 용도이므로 최소 유지)
|
||
connection-timeout: 30000 # 30초 타임아웃
|
||
idle-timeout: 600000
|
||
max-lifetime: 1800000
|
||
leak-detection-threshold: 60000 # 커넥션 누수 감지 (60초)
|
||
connection-init-sql: "SET TIME ZONE 'Asia/Seoul'; SET search_path TO signal, public; SET synchronous_commit = 'off';"
|
||
|
||
# Request 크기 설정
|
||
servlet:
|
||
multipart:
|
||
max-file-size: 50MB
|
||
max-request-size: 50MB
|
||
|
||
# Spring Batch 설정
|
||
batch:
|
||
job:
|
||
enabled: false
|
||
jdbc:
|
||
initialize-schema: never # always에서 never로 변경 (이미 수동으로 생성했으므로)
|
||
table-prefix: signal.BATCH_
|
||
|
||
logging:
|
||
level:
|
||
root: INFO
|
||
gc.mda.signal_batch: INFO
|
||
gc.mda.signal_batch.monitoring: INFO
|
||
org.springframework.batch: WARN
|
||
org.springframework.jdbc: WARN
|
||
org.postgresql: WARN
|
||
com.zaxxer.hikari: WARN
|
||
|
||
# 개발 환경 배치 설정 (성능 최적화)
|
||
vessel: # spring 하위가 아닌 최상위 레벨
|
||
# 통합선박 설정
|
||
integration:
|
||
enabled: true
|
||
datasource:
|
||
jdbc-url: jdbc:postgresql://211.208.115.83:5432/snpdb?currentSchema=public&assumeMinServerVersion=12&reWriteBatchedInserts=true
|
||
username: snp
|
||
password: snp#8932
|
||
ble-name: gis.t_ship_integration_sub # gis 스키마는 jdbc-url의 currentSchema로 지정
|
||
batch:
|
||
# Area Statistics 처리를 위한 별도 설정
|
||
area-statistics:
|
||
chunk-size: 1000 # 5000 → 1000
|
||
batch-size: 500 # 새로 추가
|
||
|
||
chunk-size: 10000
|
||
page-size: 5000
|
||
partition-size: 12
|
||
|
||
# 성능 최적화 설정
|
||
optimization:
|
||
enabled: true
|
||
dynamic-chunk-sizing: true
|
||
memory-optimization: true
|
||
cache-optimization: true
|
||
thread-pool-optimization: true
|
||
# 동적 청크 크기 조정
|
||
chunk:
|
||
min-size: 1000
|
||
max-size: 20000
|
||
adjustment-factor: 0.2
|
||
# 메모리 임계값
|
||
memory:
|
||
warning-threshold: 70
|
||
critical-threshold: 85
|
||
optimization-threshold: 80
|
||
# 캐시 설정
|
||
cache:
|
||
min-hit-rate: 70
|
||
area-boundary-size: 5000
|
||
|
||
# Reader 최적화
|
||
fetch-size: 200000
|
||
use-cursor-reader: true
|
||
|
||
# Bulk Insert 최적화
|
||
bulk-insert:
|
||
batch-size: 10000
|
||
parallel-threads: 8
|
||
use-binary-copy: false
|
||
|
||
# Writer 설정
|
||
writer:
|
||
use-advisory-lock: false
|
||
parallel-threads: 4
|
||
|
||
# 재시도 설정
|
||
retry:
|
||
max-attempts: 3
|
||
initial-interval: 1000
|
||
max-interval: 10000
|
||
multiplier: 2
|
||
|
||
# 스케줄러 설정
|
||
scheduler:
|
||
enabled: true
|
||
incremental:
|
||
delay-minutes: 3 # 데이터 수집 지연 고려
|
||
|
||
# Batch 메타데이터 정리 설정
|
||
metadata:
|
||
cleanup:
|
||
enabled: true # 자동 정리 활성화
|
||
retention-days: 21 # 보존 기간 (30일)
|
||
dry-run: false # false: 실제 삭제, true: 테스트만
|
||
|
||
# 궤적 비정상 검출 설정
|
||
track:
|
||
abnormal-detection:
|
||
large-gap-threshold-hours: 4 # 이 시간 이상 gap은 연결 안함
|
||
extreme-speed-threshold: 1000 # 이 속도 이상은 무조건 비정상 (knots)
|
||
enable-merger-filtering: false # VesselTrackMerger 필터링 활성화 (기본: false)
|
||
|
||
# 타임아웃 설정
|
||
query-timeout: 1800 # 30분
|
||
lock:
|
||
timeout: 30
|
||
max-retry: 5
|
||
|
||
# Health Check 설정
|
||
health:
|
||
job-timeout-hours: 2
|
||
min-partition-count: 1
|
||
|
||
# 그리드 설정
|
||
grid:
|
||
mode: haegu
|
||
haegu:
|
||
cache-enabled: true
|
||
cache-size: 2000
|
||
|
||
# 선박 최신 위치 캐시 설정 (운영 환경 활성화)
|
||
cache:
|
||
latest-position:
|
||
enabled: true # 운영 환경: 활성화
|
||
ttl-minutes: 60 # 60분 TTL
|
||
max-size: 60000 # 최대 60,000척
|
||
refresh-interval-minutes: 2 # 2분치 데이터 조회 (수집 지연 고려)
|
||
|
||
# L2 HourlyTrackCache 간소화 (운영 환경 활성화)
|
||
hourly-simplification:
|
||
enabled: true # 운영 환경: 활성화
|
||
|
||
# 비정상 궤적 검출 설정 (개선됨)
|
||
abnormal-detection:
|
||
enabled: true
|
||
5min-speed-threshold: 500 # 5분 집계 비정상 속도 임계값 (200 knots로 완화)
|
||
# 비정상 판정 기준 (명백한 비정상만 검출하도록 완화)
|
||
thresholds:
|
||
# 정박/저속 판단 기준
|
||
min-movement-nm: 0.05 # 최소 이동거리 (정박 판단)
|
||
stationary-speed-knots: 0.5 # 정박 속도 기준
|
||
|
||
# 선박 관련 임계값
|
||
vessel-physical-limit-knots: 100.0 # 선박 물리적 한계
|
||
vessel-abnormal-speed-knots: 200.0 # 선박 명백한 비정상 속도
|
||
|
||
# 항공기 관련 임계값
|
||
aircraft-physical-limit-knots: 600.0 # 항공기 물리적 한계
|
||
aircraft-abnormal-speed-knots: 800.0 # 항공기 명백한 비정상 속도
|
||
|
||
# 거리 관련 임계값
|
||
base-distance-5min-nm: 20.0 # 5분 기준 거리 (20nm로 완화)
|
||
extreme-distance-5min-nm: 100.0 # 5분간 극단적 이동거리
|
||
|
||
# Hourly/Daily 전용 임계값
|
||
hourly-daily-speed-limit: 500.0 # 시간/일 집계시 극단적 속도만 검출
|
||
|
||
# 기타 설정
|
||
distance-tolerance: 3.0 # 거리 허용 배수 (3.0으로 완화)
|
||
time-scaling-method: "sqrt" # 시간 스케일링 방법 (sqrt)
|
||
# 캐시 설정
|
||
cache:
|
||
previous-track-size: 10000 # 이전 궤적 캐시 크기
|
||
ttl-hours: 24 # 캐시 TTL
|
||
# 처리 옵션
|
||
processing:
|
||
remove-abnormal-segments: true # 비정상 구간 제거 여부
|
||
save-corrected-tracks: true # 보정된 궤적 저장 여부
|
||
exclude-stationary-vessels: false # 정박 선박 제외 여부
|
||
lenient-mode: true # 관대한 모드 활성화
|
||
|
||
# 파티션 관리 설정 (운영 환경 - application.yml 설정 오버라이드)
|
||
partition:
|
||
# 운영 환경에서는 더 긴 보관 기간 설정 가능
|
||
default-retention:
|
||
daily-partitions-retention-days: 7 # 일별 파티션 7일 보관
|
||
monthly-partitions-retention-months: 3 # 월별 파티션 3개월 보관
|
||
|
||
tables:
|
||
# 중요 데이터는 더 오래 보관
|
||
t_area_vessel_tracks:
|
||
retention-days: 60 # 구역별 선박 항적: 60일
|
||
t_grid_vessel_tracks:
|
||
retention-days: 30 # 해구별 선박 항적: 30일
|
||
t_vessel_tracks_daily:
|
||
retention-months: 0 # 일별 항적: 영구 보관
|
||
t_abnormal_tracks:
|
||
retention-months: 0 # 비정상 항적: 영구 보관
|
||
|
||
# S&P AIS API 캐시 TTL (운영: 120분)
|
||
app:
|
||
cache:
|
||
ais-target:
|
||
ttl-minutes: 120
|
||
ais-api:
|
||
username: 7cc0517d-5ed6-452e-a06f-5bbfd6ab6ade
|
||
password: 2LLzSJNqtxWVD8zC
|
||
|
||
# 일일 항적 데이터 인메모리 캐시
|
||
cache:
|
||
daily-track:
|
||
enabled: true
|
||
retention-days: 14 # D-1 ~ D-14 (2주, DP 간소화로 메모리 절감)
|
||
max-memory-gb: 10 # 최대 10GB (DP 간소화 후 일 ~400MB × 14일 ≈ 6GB + 여유)
|
||
warmup-async: true # 비동기 워밍업 (서버 시작 차단 없음)
|
||
|
||
# 항적 데이터 메모리 예산 (64GB JVM 기준)
|
||
track:
|
||
memory-budget:
|
||
total-budget-gb: 64 # 전체 JVM 힙
|
||
cache-budget-gb: 35 # L1+L2+L3 캐시 (L3 5GB + L2 ~14GB + L1 ~3GB + 여유 13GB)
|
||
query-budget-gb: 20 # REST/WebSocket 동시 쿼리 (동시 60쿼리 × ~300MB)
|
||
max-single-query-gb: 5 # 단일 쿼리 상한
|
||
estimation-correction-factor: 1.8 # 실측 기반 보정 계수
|
||
queue-timeout-seconds: 60
|
||
warning-threshold: 0.8
|
||
critical-threshold: 0.95
|
||
|
||
# WebSocket 부하 제어 설정
|
||
websocket:
|
||
query:
|
||
max-concurrent-global: 30 # 서버 전체 동시 실행 쿼리 상한 (메모리 보호: 60→30)
|
||
max-per-session: 10 # 세션당 동시 쿼리 상한 (20→10)
|
||
queue-timeout-seconds: 60 # 글로벌 대기 큐 타임아웃 (슬롯 감소 보완: 30→60)
|
||
transport:
|
||
message-size-limit-mb: 2 # 단일 STOMP 메시지 상한 (50→2MB, 청크 1024KB 기준)
|
||
send-buffer-size-limit-mb: 50 # 세션당 송신 버퍼 상한 (사전 할당 아님, 최악 30×50MB=1.5GB)
|
||
outbound-queue-capacity: 200 # 아웃바운드 메시지 큐 (5000→200)
|
||
send-time-limit-seconds: 30 # 메시지 전송 시간 제한
|
||
memory:
|
||
heap-reject-threshold: 0.85 # 힙 사용률 85% 초과 시 새 쿼리 대기열 전환 (기본 20~24GB → 정상시 50% 미만)
|
||
session:
|
||
idle-timeout-ms: 15000 # 세션 유휴 타임아웃 15초 (60s → 15s)
|
||
server-heartbeat-ms: 5000 # 서버 하트비트 5초 (10s → 5s)
|
||
client-heartbeat-ms: 5000 # 클라이언트 하트비트 5초 (10s → 5s)
|
||
sockjs-disconnect-delay-ms: 5000 # SockJS 해제 지연 5초 (30s → 5s)
|
||
send-time-limit-seconds: 30 # 메시지 전송 시간 제한 30초 (120s → 30s)
|
||
|
||
# REST V2 부하 제어 설정
|
||
rest:
|
||
v2:
|
||
query:
|
||
timeout-seconds: 30 # 슬롯 대기 타임아웃 (초)
|
||
max-total-points: 500000 # 응답 총 포인트 상한
|
||
|
||
# 액추에이터 설정
|
||
management:
|
||
endpoints:
|
||
web:
|
||
exposure:
|
||
include: health,info,metrics,prometheus,env,loggers,threaddump,heapdump,scheduledtasks
|
||
endpoint:
|
||
health:
|
||
show-details: always
|
||
show-components: always
|
||
metrics:
|
||
tags:
|
||
application: vessel-batch-aggregation
|
||
environment: prod
|