- CollectDB 다중 신호 수집 → S&P Global AIS API 단일 수집으로 전환 - sig_src_cd + target_id 이중 식별자 → mmsi(VARCHAR) 단일 식별자 - t_vessel_latest_position → t_ais_position 테이블 전환 - 레거시 배치/유틸 ~30개 클래스 삭제 (VesselAggregationJobConfig, ShipKindCodeConverter 등) - AisTargetCacheManager 기반 캐시 이중 구조 (최신위치 + 트랙 버퍼) - CacheBasedVesselTrackDataReader + CacheBasedTrackJobListener 신규 추가 - VesselStaticStepConfig: 정적정보 CDC 변경 검출 + hourly job 편승 - SignalKindCode enum: vesselType/extraInfo 기반 선종 자동 분류 - WebSocket/STOMP 전체 mmsi 전환 (StompTrackStreamingService ~40곳) - 모니터링/성능 최적화 코드 mmsi 기반 전환 - DataSource 설정 통합 (snpdb 단일 DB) - AreaBoundaryCache Polygon→Geometry 캐스트 수정 (MULTIPOLYGON 지원) - ConcurrentHashMap 적용 (VesselTrackStepConfig 동시성 버그 수정) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
185 lines
5.1 KiB
Bash
185 lines
5.1 KiB
Bash
#!/bin/bash
|
|
|
|
# Query 전용 서버 실행 스크립트 (10.29.17.90)
|
|
# 배치 Job 없이 조회 API만 제공
|
|
# Java 17 경로 명시적 지정
|
|
|
|
# 애플리케이션 경로
|
|
APP_HOME="/devdata/apps/bridge-db-monitoring"
|
|
JAR_FILE="$APP_HOME/vessel-batch-aggregation.jar"
|
|
|
|
# Java 17 경로
|
|
JAVA_HOME="/devdata/apps/jdk-17.0.8"
|
|
JAVA_BIN="$JAVA_HOME/bin/java"
|
|
|
|
# 로그 디렉토리
|
|
LOG_DIR="$APP_HOME/logs"
|
|
mkdir -p $LOG_DIR
|
|
|
|
echo "================================================"
|
|
echo "Vessel Query API Server - Query Only Mode"
|
|
echo "Start Time: $(date)"
|
|
echo "================================================"
|
|
|
|
# 경로 확인
|
|
echo "Environment Check:"
|
|
echo "- App Home: $APP_HOME"
|
|
echo "- JAR File: $JAR_FILE"
|
|
echo "- Java Path: $JAVA_BIN"
|
|
echo "- Java Version: $($JAVA_BIN -version 2>&1 | head -1)"
|
|
|
|
# JAR 파일 존재 확인
|
|
if [ ! -f "$JAR_FILE" ]; then
|
|
echo "ERROR: JAR file not found at $JAR_FILE"
|
|
exit 1
|
|
fi
|
|
|
|
# Java 실행 파일 확인
|
|
if [ ! -x "$JAVA_BIN" ]; then
|
|
echo "ERROR: Java not found or not executable at $JAVA_BIN"
|
|
exit 1
|
|
fi
|
|
|
|
# 서버 정보 확인
|
|
echo ""
|
|
echo "Server Info:"
|
|
echo "- Hostname: $(hostname)"
|
|
echo "- CPU Cores: $(nproc)"
|
|
echo "- Total Memory: $(free -h | grep Mem | awk '{print $2}')"
|
|
echo "- PostgreSQL Version: $(psql --version 2>/dev/null | head -1 || echo 'PostgreSQL client not in PATH')"
|
|
|
|
# 환경 변수 설정 (query 프로파일 - 배치 비활성화!)
|
|
export SPRING_PROFILES_ACTIVE=query
|
|
|
|
echo ""
|
|
echo "Profile Settings:"
|
|
echo "- Active Profile: QUERY (Batch Jobs Disabled)"
|
|
echo "- Query DB: 10.29.17.90:5432/mpcdb2 (Local DB)"
|
|
echo "- Batch Jobs: DISABLED"
|
|
echo "- Scheduler: DISABLED"
|
|
|
|
# JVM 옵션 (서버 메모리에 맞게 조정)
|
|
TOTAL_MEM=$(free -g | grep Mem | awk '{print $2}')
|
|
JVM_HEAP=$((TOTAL_MEM / 8)) # 전체 메모리의 12.5% 사용 (배치 없으므로 적게)
|
|
|
|
# 최소 4GB, 최대 16GB로 제한
|
|
if [ $JVM_HEAP -lt 4 ]; then
|
|
JVM_HEAP=4
|
|
elif [ $JVM_HEAP -gt 16 ]; then
|
|
JVM_HEAP=16
|
|
fi
|
|
|
|
CPU_CORES=$(nproc)
|
|
|
|
JAVA_OPTS="-Xms${JVM_HEAP}g -Xmx${JVM_HEAP}g \
|
|
-XX:+UseG1GC \
|
|
-XX:G1HeapRegionSize=32m \
|
|
-XX:MaxGCPauseMillis=200 \
|
|
-XX:InitiatingHeapOccupancyPercent=35 \
|
|
-XX:G1ReservePercent=15 \
|
|
-XX:+UseStringDeduplication \
|
|
-XX:+ParallelRefProcEnabled \
|
|
-XX:+ExplicitGCInvokesConcurrent \
|
|
-XX:ParallelGCThreads=$((CPU_CORES / 2)) \
|
|
-XX:ConcGCThreads=$((CPU_CORES / 4)) \
|
|
-XX:MaxMetaspaceSize=512m \
|
|
-XX:+HeapDumpOnOutOfMemoryError \
|
|
-XX:HeapDumpPath=$LOG_DIR/heapdump.hprof \
|
|
-Xlog:gc*:file=$LOG_DIR/gc.log:time,uptime,level,tags:filecount=5,filesize=100M \
|
|
-Dfile.encoding=UTF-8 \
|
|
-Duser.timezone=Asia/Seoul \
|
|
-Djava.security.egd=file:/dev/./urandom \
|
|
-Dspring.profiles.active=query"
|
|
|
|
echo "- JVM Heap Size: ${JVM_HEAP}GB"
|
|
|
|
# 기존 프로세스 확인 및 종료
|
|
echo ""
|
|
echo "Checking for existing process..."
|
|
PID=$(pgrep -f "$JAR_FILE")
|
|
if [ ! -z "$PID" ]; then
|
|
echo "Stopping existing process (PID: $PID)..."
|
|
kill -15 $PID
|
|
|
|
# 프로세스 종료 대기 (최대 30초)
|
|
for i in {1..30}; do
|
|
if ! kill -0 $PID 2>/dev/null; then
|
|
echo "Process stopped successfully."
|
|
break
|
|
fi
|
|
if [ $i -eq 30 ]; then
|
|
echo "Force killing process..."
|
|
kill -9 $PID
|
|
fi
|
|
sleep 1
|
|
done
|
|
fi
|
|
|
|
# 작업 디렉토리로 이동
|
|
cd $APP_HOME
|
|
|
|
# 애플리케이션 실행
|
|
echo ""
|
|
echo "Starting application in QUERY-ONLY mode..."
|
|
echo "Command: $JAVA_BIN $JAVA_OPTS -jar $JAR_FILE"
|
|
echo ""
|
|
|
|
# nohup으로 백그라운드 실행
|
|
nohup $JAVA_BIN $JAVA_OPTS -jar $JAR_FILE \
|
|
> $LOG_DIR/app.log 2>&1 &
|
|
|
|
NEW_PID=$!
|
|
echo "Application started with PID: $NEW_PID"
|
|
|
|
# PID 파일 생성
|
|
echo $NEW_PID > $APP_HOME/vessel-query.pid
|
|
|
|
# 시작 확인 (30초 대기)
|
|
echo "Waiting for application startup..."
|
|
STARTUP_SUCCESS=false
|
|
for i in {1..30}; do
|
|
if grep -q "Started SignalBatchApplication" $LOG_DIR/app.log 2>/dev/null; then
|
|
echo "✅ Application started successfully!"
|
|
STARTUP_SUCCESS=true
|
|
break
|
|
fi
|
|
echo -n "."
|
|
sleep 1
|
|
done
|
|
|
|
if [ "$STARTUP_SUCCESS" = false ]; then
|
|
echo ""
|
|
echo "⚠️ Application startup timeout. Check logs for errors."
|
|
echo "Log file: $LOG_DIR/app.log"
|
|
tail -20 $LOG_DIR/app.log
|
|
fi
|
|
|
|
echo ""
|
|
echo "================================================"
|
|
echo "Deployment Complete!"
|
|
echo "- Mode: QUERY ONLY (No Batch Jobs)"
|
|
echo "- PID: $NEW_PID"
|
|
echo "- PID File: $APP_HOME/vessel-query.pid"
|
|
echo "- Log: $LOG_DIR/app.log"
|
|
echo "- Monitor: tail -f $LOG_DIR/app.log"
|
|
echo "================================================"
|
|
|
|
# 초기 상태 확인
|
|
sleep 5
|
|
echo ""
|
|
echo "Initial Status Check:"
|
|
curl -s http://localhost:8090/actuator/health 2>/dev/null | python -m json.tool || echo "Health endpoint not yet available"
|
|
|
|
# 리소스 사용량 표시
|
|
echo ""
|
|
echo "Resource Usage:"
|
|
ps aux | grep $NEW_PID | grep -v grep
|
|
|
|
# 빠른 명령어 안내
|
|
echo ""
|
|
echo "Useful Commands:"
|
|
echo "- Stop: kill -15 \$(cat $APP_HOME/vessel-query.pid)"
|
|
echo "- Logs: tail -f $LOG_DIR/app.log"
|
|
echo "- Status: curl http://localhost:8090/actuator/health"
|
|
echo "- API Test: curl http://localhost:8090/api/gis/areas"
|