FlowKat 전체 아키텍처 및 기술 스택
기술지원 엔지니어가 설치 전 전체 시스템 구조를 파악하기 위한 문서다. Layer 2(파라미터), Layer 3(고객 응대) 문서의 기초가 된다.
1. 전체 아키텍처 다이어그램
"고객님, FlowKat은 크게 두 부분으로 나뉩니다. 고객님 서버에 설치하는 에이전트와, 저희가 구축해드리는 모니터링 서버입니다. 에이전트는 기존 애플리케이션 성능에 거의 영향을 주지 않으면서 데이터를 수집하고, 모니터링 서버에서 분석과 시각화를 담당합니다."
FlowKat APM은 **에이전트(수집)**와 서버(저장/분석/UI) 두 계층으로 구성된다. 고객 서버에 설치된 에이전트가 성능 데이터를 수집하고, FlowKat 서버의 Docker Compose 클러스터가 저장/분석/시각화를 담당한다.
서비스 시작 순서
Docker Compose의 depends_on + healthcheck 설정에 의해 아래 순서로 기동된다.
2. 서비스 관계 매트릭스
FlowKat은 7개의 Docker 서비스로 구성된다. Core Services 4개 + TX-Mining Services 3개이다.
| 서비스 | 내부 포트 | 외부 포트 | 의존 서비스 | Docker 이미지 | 기술 스택 | JVM 힙 (prod) |
|---|---|---|---|---|---|---|
| collect-server | 6100/tcp, 6180/tcp | 6100 (host mode) | postgres (healthy) | registry.flowkat.dev/flowkat/collect-server | Java 8 (Corretto), Maven | -Xmx2g -Xms2g |
| api-server | 6188 | 미노출 (내부) | collect-server | registry.flowkat.dev/flowkat/api-server | Java 8 (Corretto), Maven | -Xmx1g -Xms1g |
| dashboard-server | 6600 | 미노출 (내부) | api-server | registry.flowkat.dev/flowkat/dashboard-server | Java 8, Gradle 8.5 | -Xmx2g -Xms1g |
| ui-server | 8080 | 6300 | dashboard-server | registry.flowkat.dev/flowkat/ui-server | Next.js, PM2, Node.js LTS | N/A (Node.js 2GB heap) |
| tx-mining-api | 8090 | 8090 | valkey (healthy), postgres (healthy) | registry.flowkat.dev/flowkat/mining-server | Spring Boot 3.x, JDK 17, Gradle 8.5 | -Xmx1g -Xms512m |
| valkey | 6379 | 6380 | 없음 | valkey/valkey:9.0-alpine | Valkey 9.0 (Redis-compatible) | N/A |
| postgres | 5432 | 5433 | 없음 | flowkat/postgres-ai:16.5 | PostgreSQL 16 + pgvector 0.8 + pg_partman | N/A (shm_size: 1gb) |
3. 고객 용어 ↔ 기술 스택 매핑
"고객님이 말씀하시는 '대시보드'는 저희 시스템에서 dashboard-server라는 구성요소입니다. 아래 표를 참고하시면 고객님이 사용하시는 용어와 실제 기술 구성요소가 어떻게 매핑되는지 확인하실 수 있습니다."
현장에서 고객/엔지니어가 사용하는 용어와 실제 기술 구성 요소의 매핑이다. 13개 항목을 포함한다.
| 고객이 말하는 것 | 실제 구성 요소 | 기술 스택 | 설정 위치 |
|---|---|---|---|
| "수집 서버" / "컬렉터" | collect-server 컨테이너 | Java 8 (Corretto), TCP 수신 | volumes/collect-server/conf/ |
| "API 서버" | api-server 컨테이너 | Java 8, REST API (내부 6188) | volumes/api-server/conf/ |
| "대시보드" / "웹 서버" | dashboard-server 컨테이너 | Java 8, Spring Boot, H2 내장DB | volumes/dashboard-server/config/ |
| "화면" / "UI" / "프론트" | ui-server 컨테이너 | Next.js, PM2 클러스터, Nginx 프록시 | .env (NEXTAUTH_URL, PM2_INSTANCES) |
| "트랜잭션 익스플로러" / "마이닝" | tx-mining-api 컨테이너 | Spring Boot 3.x, JDK 17, REST API | .env (TX_MINING_ENABLED) |
| "캐시" / "Redis" | valkey 컨테이너 | Valkey 9.0 (Redis-compatible), AOF 영속화 | volumes/mining-server/config/valkey.conf |
| "DB" / "PostgreSQL" | postgres 컨테이너 | PostgreSQL 16 + pgvector + pg_partman | .env (POSTGRES_DB/USER/PASSWORD) |
| "에이전트" / "자바 에이전트" | agent.java 디렉토리 | Java 8+ 바이트코드 계측 | 고객 서버 /opt/flowkat/agent.java |
| "레거시 에이전트" | agent.java_6_7 디렉토리 | Java 6/7 호환 에이전트 | 고객 서버 /opt/flowkat/agent.java_6_7 |
| "호스트 에이전트" | agent.host 디렉토리 | OS 레벨 메트릭 수집 (sigar JNI) | 고객 서버 /opt/flowkat/agent.host |
| "컨테이너 에이전트" | agent.host.container 디렉토리 | K8s/컨테이너 메트릭 (oshi-core) | K8s Pod 내 배포 |
| "알림" / "Sentry" | collect-server 플러그인 | HTTP 콜백 (SENTRY_ADDRESS) | .env (SENTRY_ADDRESS) |
| "XLog 플러그인" | collect-server PostgreSQL 플러그인 | JDBC → PostgreSQL 직접 기록 | .env (server_plugin_postgres_*) |
4. 포트/프로토콜 매트릭스
- 고객사 방화벽 담당자에게 6100(TCP), 6300(TCP) 포트 개방 요청 완료
- 에이전트 서버 → FlowKat 서버 간 6100 포트 통신 테스트 (
nc -zv <서버IP> 6100) - 사용자 PC → FlowKat 서버 간 6300 포트 접속 테스트 (브라우저)
- 내부 전용 포트(5433, 6380) 외부 노출 차단 확인
방화벽 설정 시 참조한다. 8개 포트를 대상으로 한다.
| 포트 | 프로토콜 | 서비스 | 방화벽 개방 필요 | 설명 |
|---|---|---|---|---|
| 6100 | TCP | collect-server | O (인바운드) | 에이전트 데이터 수집 (V3 TCP 전용) |
| 6180 | TCP | collect-server | X (내부) | Collect Server HTTP 관리 API |
| 6188 | TCP | api-server | X (내부) | API Server REST (컨테이너 간 통신) |
| 6300 | TCP | ui-server | O (인바운드) | 웹 UI 접속 (사용자 브라우저) |
| 6600 | TCP | dashboard-server | X (내부) | Dashboard Server (ui-server에서 프록시) |
| 8090 | TCP | tx-mining-api | 선택 (인바운드) | TX-Mining REST API |
| 6380 | TCP | valkey | X (내부 권장) | Valkey (Redis-compatible) 캐시 |
| 5433 | TCP | postgres | X (내부 권장) | PostgreSQL TX-Mining DB |
네트워크 모드별 포트 노출 차이
collect-server는 배포 환경에 따라 네트워크 모드가 다르다.
| 모드 | collect-server 네트워크 | XLog Plugin DB 접속 | 비고 |
|---|---|---|---|
| bridge (Development/Demo) | bridge 네트워크, 포트 매핑 | 172.17.0.1:5433 (Docker 게이트웨이) | 네트워크 격리 |
| host (Production/Aircap) | 호스트 네트워크 직접 사용 | 127.0.0.1:5433 (호스트 포트) | 라이선스 검증용 호스트 IP 필요 |
5. 환경별 차이점
FlowKat은 Development, Production, Aircap, Demo 4개 환경을 지원한다. flowkat-env-setup.sh 스크립트로 대화형 설정이 가능하다.
| 항목 | Development | Production | Aircap | Demo |
|---|---|---|---|---|
| DEPLOYMENT_ENV | development | production | aircap | demo |
| FLOWKAT_VERSION | latest | 5.0.27 (고정) | 5.0.27 (고정) | 5.0.27 (고정) |
| NETWORK_MODE_COLLECT | bridge | host | host | bridge |
| COLLECT_POSTGRES_HOST | 172.17.0.1 | 127.0.0.1 | 127.0.0.1 | 172.17.0.1 |
| SENTRY_ADDRESS | http://ui-server:8080 | http://127.0.0.1:6300 | http://127.0.0.1:6300 | http://ui-server:8080 |
| NEXTAUTH_URL | http://localhost:6300 | https://flowkat.example.com | http://{서버IP}:6300 | http://localhost:6300 |
| USE_SECURE_COOKIES | false | true | false | false |
| AUTH_TRUST_HOST | 미설정 | true | true | 미설정 |
| FLOWKAT_API_SOCKET_URL | 미설정 (직접 연결) | 미설정 (Nginx 프록시 선택) | http://{서버IP}:6300 | 미설정 (직접 연결) |
| TXMINING_PROFILE | dev | prod | prod | dev |
| CORS_ORIGINS | localhost:6300,localhost:3000 | https://flowkat.example.com | localhost:3000 | localhost:6300,localhost:3000 |
| POSTGRES_PASSWORD | txmining | CHANGE_ME_IN_PRODUCTION | CHANGE_ME_IN_PRODUCTION | flowkat_demo_123 |
| RESTART_POLICY | unless-stopped | always | always | unless-stopped |
| Collect Server 힙 | -Xmx1g -Xms512m | -Xmx2g -Xms2g | -Xmx2g -Xms2g | -Xmx512m -Xms256m |
| API Server 힙 | -Xmx512m -Xms256m | -Xmx1g -Xms1g | -Xmx1g -Xms1g | -Xmx256m -Xms128m |
| Dashboard Server 힙 | -Xmx1g -Xms512m | -Xmx2g -Xms1g | -Xmx2g -Xms1g | -Xmx512m -Xms256m |
| TX-Mining API 힙 | -Xmx512m -Xms256m | -Xmx1g -Xms512m | -Xmx1g -Xms512m | -Xmx512m -Xms256m |
| 최소 총 메모리 | ~3GB | ~7GB | ~7GB | ~1.5GB |
6. 데이터 흐름
데이터는 수집 → 저장 → 조회 → 표시 순서로 흐른다.
데이터 흐름 시퀀스
7. 릴리즈 번들 구조
릴리즈 번들은 flowkat-release-{version}.tar.gz 형태로 배포된다. Docker 이미지 7개 + 에이전트 4개 + 환경 설정 + 관리 스크립트를 하나의 패키지에 포함한다.
flowkat-release-{version}/
├── images/ # Docker 이미지 tar (7개)
│ ├── collect-server.tar
│ ├── api-server.tar
│ ├── dashboard-server.tar
│ ├── ui-server.tar
│ ├── mining-server.tar
│ ├── valkey.tar
│ └── postgres-ai.tar
├── agents/ # 에이전트 디렉토리 (4개)
│ ├── agent.java/
│ ├── agent.java_6_7/
│ ├── agent.host/
│ └── agent.host.container/
├── dockerfiles/ # 환경별 .env + Dockerfile
│ ├── .env (환경 설정)
│ └── Dockerfile
├── volumes/ # 볼륨 템플릿
│ ├── api-server/conf/
│ ├── collect-server/conf/, database/, filedump/, plugin/
│ ├── dashboard-server/config/dashboard/, META_H2/
│ ├── ui-server/uploads/
│ └── mining-server/config/
├── docker-compose.yaml
├── start-all.sh / stop-all.sh # 서비스 시작/중지
├── load-images.sh # 이미지 일괄 로드
├── flowkat-env-setup.sh # 환경 설정 (대화형)
├── flowkat-volume-manager.sh # 볼륨 초기화/백업/복원
├── flowkat-cli.sh # 서비스 관리 CLI
├── docker-image.sh # 이미지 save/load 유틸
├── check-collect-server.sh # Collect Server 헬스체크
├── check-tx-mining.sh # TX-Mining 헬스체크
└── README.md
CI/CD 파이프라인 (Jenkins Release)
빌드부터 릴리즈 번들 생성까지의 전체 파이프라인이다. ARM 호스트에서는 QEMU 에뮬레이션으로 amd64 이미지를 크로스 빌드한다.
빌드 산출물
| Docker 이미지 | 빌드 도구 | 기반 이미지 | 레지스트리 |
|---|---|---|---|
| collect-server | Maven (Java 8) | amazoncorretto:8-alpine-jdk | registry.flowkat.dev/flowkat/ |
| api-server | Maven (Java 8) | amazoncorretto:8-alpine-jdk | registry.flowkat.dev/flowkat/ |
| dashboard-server | Gradle 8.5 (Java 8) | (빌드 시 생성) | registry.flowkat.dev/flowkat/ |
| ui-server | npm (Node.js LTS) | (빌드 시 생성) | registry.flowkat.dev/flowkat/ |
| mining-server | Gradle 8.5 (Java 17) | amazoncorretto:17-alpine | registry.flowkat.dev/flowkat/ |
| valkey | (외부 이미지) | valkey/valkey:9.0-alpine | 번들 포함 (pull) |
| postgres-ai | Multi-stage (pgvector 빌드) | postgresql-partman:16-5 | flowkat/postgres-ai:16.5 |
에이전트 패키지 (Docker 외부)
| 에이전트 | 대상 환경 | 배포 방식 |
|---|---|---|
| agent.java | Java 8+ 애플리케이션 서버 | 디렉토리 복사 (/opt/flowkat/agent.java) |
| agent.java_6_7 | Java 6/7 레거시 서버 | 디렉토리 복사 (/opt/flowkat/agent.java_6_7) |
| agent.host | 물리/VM 서버 (sigar JNI) | 디렉토리 복사 (/opt/flowkat/agent.host) |
| agent.host.container | K8s/컨테이너 (oshi-core) | 디렉토리 복사 (/opt/flowkat/agent.host.container) |
Docker 레지스트리 정보
| 항목 | 값 |
|---|---|
| 레지스트리 주소 | registry.flowkat.dev |
| 이미지 프리픽스 | registry.flowkat.dev/flowkat/ |
| 인증 | Jenkins Credentials (flowkat-registry) |
| 빌드 플랫폼 | linux/amd64 (ARM 호스트에서 QEMU 에뮬레이션) |
| 버전 태깅 | {version}.B{build_number} + latest |
| 릴리즈 업로드 | GoKAPI (file.papercraft.dev, 7일 보관, 10회 다운로드) |
| GitHub 릴리즈 | papercraft-projects/flowkat |
| 알림 | Mattermost |
8. 관리 스크립트
릴리즈 번들에 포함된 8개 운영 스크립트다.
| 스크립트 | 용도 | 실행 시점 |
|---|---|---|
flowkat-env-setup.sh | 대화형 환경 설정 (dev/prod/aircap/demo) | 최초 설치, 환경 변경 시 |
flowkat-volume-manager.sh | 볼륨 초기화, 백업, 복원, 정리 | 최초 설치, 백업/복원 시 |
flowkat-cli.sh | 서비스 관리, 로그 조회, 헬스체크 | 운영 중 |
docker-image.sh | Docker 이미지 save/load (에어갭 전용) | 오프라인 이미지 전송 시 |
load-images.sh | 릴리즈 번들 이미지 일괄 로드 | 번들 설치 시 |
start-all.sh / stop-all.sh | 전체 서비스 시작/중지 | 운영 |
check-collect-server.sh | Collect Server 헬스체크 | 모니터링/진단 |
check-tx-mining.sh | TX-Mining 인프라 헬스체크 | 모니터링/진단 |
헬스체크 매트릭스
| 서비스 | 헬스체크 방식 | 엔드포인트 / 명령어 | 간격 | 타임아웃 | 재시도 |
|---|---|---|---|---|---|
| collect-server | 프로세스 확인 | ps aux | grep java | grep collect.server | 30s | 10s | 3회 |
| api-server | 미설정 | - | - | - | - |
| dashboard-server | 미설정 | - | - | - | - |
| ui-server | 미설정 | - | - | - | - |
| tx-mining-api | HTTP | curl -f http://localhost:8090/api/v1/health | 30s | 10s | 3회 |
| valkey | CLI | valkey-cli ping | 10s | 5s | 3회 |
| postgres | CLI | pg_isready -U txmining -d txmining | 10s | 5s | 3회 |
9. 데이터 수집 원리
FlowKat 에이전트가 성능 데이터를 Collect Server로 전달하는 내부 동작 원리를 설명한다.
9.1 TCP 통신 방식 (V3 TLV Netty)
에이전트는 Collect Server TCP 포트 6100으로 단일 영구 TCP 연결을 맺는다. V3 프로토콜은 Netty 4.2.10 기반 TLV(Type-Length-Value) 프레이밍을 사용한다. V1/V2 프로토콜은 5.0 이후 폐기되었다.
재연결 메커니즘 (이중 경로)
| 경로 | 트리거 | 동작 |
|---|---|---|
| 경로 1 (정상 단절) | TlvReconnectHandler.channelInactive() 발동 | 지수 백오프 + Jitter(0~30%) 재연결 |
| 경로 2 (최초 연결 실패) | ChannelFuture 실패 리스너 | scheduleRetryAfterFailure() 호출 후 동일 백오프 |
두 경로 모두 flowkat.net.tlv.TlvClientBootstrap에 구현되어 있으며, 최대 재시도(net_collector_tcp_reconnect_max_retry: 30) 후 주기적 재시도(5분)로 전환된다.
재연결 중에는 DataProxy.sendDirect()가 연결 없음을 감지하여 해당 패킷을 드롭한다(A130 로그).
9.2 수집 데이터 유형
에이전트는 세 가지 Pack 타입을 전송한다. 각 타입은 flowkat.lang.pack 패키지에 정의되어 있다.
| Pack 타입 | 클래스 | 수집 내용 | 전송 방식 |
|---|---|---|---|
| XLog (트랜잭션) | XLOG 데이터, XLogProfilePack2 | HTTP 트랜잭션, 응답 시간, SQL, API 호출 등 | 트랜잭션 완료 시 즉시 (sendDirect) |
| Counter (메트릭) | 성능 카운터 데이터, Interaction성능 카운터 데이터 | TPS, 응답 시간, 활성 서비스, JVM 힙, CPU 등 | 주기적 배치 전송 |
| Text (문자열) | 텍스트 데이터 | SQL 텍스트, 메서드명, 서비스명, 에러 메시지 등 | 최초 등장 시 1회 전송 (해시 캐시 활용) |
Text 타입 세부 분류 (flowkat.lang.TextTypes):
| TextType | 용도 |
|---|---|
SQL | JDBC 쿼리 텍스트 |
SERVICE | URL/서비스 경로 |
METHOD | 메서드명 (바이트코드 계측) |
APICALL | 외부 API 호출 URL |
ERROR | 예외 메시지 |
OBJECT | 에이전트 오브젝트명 |
USER_AGENT | HTTP User-Agent |
LOGIN | 로그인 사용자명 |
9.3 수집 주기
| 데이터 타입 | 수집/전송 주기 | 비고 |
|---|---|---|
| Counter (메트릭) | 5초 | CounterExecutingManager 주기 실행 |
| XLog (트랜잭션) | 실시간 (트랜잭션 완료 즉시) | 지연 서비스는 DelayedServiceManager에서 후처리 |
| Text (문자열) | on-demand (최초 등장 시) | 해시 충돌 방지를 위해 IntLinkedSet 로컬 캐시 (max: 10,000)로 중복 전송 방지 |
9.4 버퍼링 전략
에이전트는 로컬 메모리 버퍼를 최소화하는 설계를 따른다.
- XLog / Counter:
DataProxy.sendDirect()로 즉시 TCP 전송 시도. 연결 없으면 드롭 (버퍼 누적 없음). - Text:
TextDataSendThread가 별도 스레드로 큐를 비워 전송. 연결 복구 후 큐 잔존 텍스트 전송. - Collect Server 연결 실패 시: XLog와 Counter는 재연결 완료 이전 데이터가 유실된다. Text만 전송 스레드 큐에서 대기한다.
설계 의도: 에이전트 메모리 오버헤드를 최소화하기 위해 인-메모리 버퍼 축적보다 드롭 정책을 선택했다. 단기 Collect Server 장애로 인한 일부 XLog 유실은 정상 동작이다.
9.5 데이터 압축
FlowKat 에이전트는 TCP 레이어에서 별도의 애플리케이션 수준 압축을 적용하지 않는다. 대신 Text 타입 해시 캐시로 중복 문자열 전송을 억제하여 네트워크 대역폭을 최적화한다.
- SQL 텍스트: 최초 1회 전송 후 해시(
int)만 XLog에 포함 - 메서드명/서비스명: 동일하게 해시로 대체 전송
Collect Server 측에서는 TextCore가 해시-문자열 매핑을 메모리에 유지하고, 일정 주기로 TextCacheReset이 에이전트에 텍스트 캐시 리셋을 요청한다.
9.6 수집 원리 전체 흐름
관련 문서
- Layer 2: 각 모듈 파라미터 →
outline/layer2-*.md - Layer 3: 고객 응대 가이드 →
outline/layer3-*.md - 공통: 포트 전체 목록 →
outline/layer2-network-ports.md - 공통: 용어집 →
outline/common-glossary.md - Collect Server 상세: 14.collect-server.md
- Java 에이전트 상세: 10.agent-java.md