diff --git a/README.md b/README.md index 9c814408..dc2d705b 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,103 @@ Spring Boot 기반 API 서버로, Redis Stream 기반 메시지 처리와 Promet ### Infra image +## Traffic Generator +## **🚦 트래픽(Traffic) 처리 아키텍처 및 핵심 로직** + +Pooli의 핵심 도메인인 **'실시간 데이터(트래픽) 차감 및 공유 시스템'** 은 대규모 트래픽 사용 이벤트를 유실 없이 병렬로 처리하며, 가족 간 데이터 공유 풀을 안전하게 관리하기 위해 설계되었습니다. + +--- + +### **📌 1. 실시간 스트림 처리 (Event-Driven Architecture)** + +![image.png](attachment:8a8f1810-378a-4af2-a82b-90bf5a19a05d:image.png) + +```yaml + [ 데이터 사용 이벤트 유입 (Stream) ] + │ + ▼ + 개인풀(INDIVIDUAL) 차감 실행 + (내부적으로 Hydrate / Refill 연계 처리) + │ + ┌────────────────────┴────────────────────┐ + │ │ + ▼ ▼ + (잔량 충분: SUCCESS) (잔량 부족: NO_BALANCE) + │ │ + ▼ ▼ + 개인풀 차감 [ 잔여 데이터(Residual) 계산 ] + (최근 사용량 Bucket 갱신) │ + │ ▼ + │ 공유풀(SHARED) 차감 실행 + │ (내부적으로 Hydrate / Refill 연계 처리) + │ │ + │ ┌───────────────┴───────────────┐ + │ │ │ + │ ▼ ▼ + │ (공유풀 잔량 충분) (공유풀 잔량 부족) + │ │ │ + │ ▼ ▼ + │ 공유풀 차감 QoS 차단 통제 등 + │ (최근 사용량 Bucket 갱신) (일부만 차감, PARTIAL) + │ │ │ + └────────────┬────────────┴───────────────────────────────┘ + ▼ + [ 공유풀 임계치 도달 여부 확인 ] + │ + ┌──────────────┴──────────────┐ + ▼ ▼ + (임계치 이상) (임계치 미만) + │ │ + │ ▼ + │ 공유 데이터 임계치 알림 발행 + │ (Threshold Alarm Enqueue) + │ │ + └──────────────┬──────────────┘ + ▼ + [ 최종 상태(Final Status) 계산 및 반환 ] + ( SUCCESS / PARTIAL_SUCCESS / FAILED ) + +``` + +데이터 사용 이벤트는 **Redis Streams** 기반의 메시지 큐를 통해 비동기적으로 유입되며, 자체 구현한 스트림 컨슈머 러너(TrafficStreamConsumerRunner)가 이를 병렬 처리합니다. + +- **Poller & Worker Pool 구조:** 단일 Poller 스레드가 이벤트를 `BLOCK` 방식으로 읽어오면, 미리 설정된 N개의 Worker 스레드 풀이 병렬로 차감 로직을 실행하여 처리량(Throughput)을 극대화합니다. +- **Backpressure (백프레셔) 제어:** 워커 큐(Worker Queue)가 가득 차거나 스레드가 부족해질 경우, Poller의 읽기 속도를 자가 조절(Pause)하여 시스템 과부하를 방어합니다. +- **장애 복구 및 재처리 (Resilience):** 역직렬화 오류 등 스키마 불일치 건은 즉시 **DLQ(Dead Letter Queue)** 로 격리하고, 일시적 오류로 미처리된 메시지들은 **Reclaim Loop** 스케줄러가 주기적으로 회수하여 재처리합니다. + +--- + +### **⚖️ 2. 이중 차감 오케스트레이션 (Deduction Orchestration)** + +트래픽 차감은 TrafficDeductOrchestratorService를 중심으로 **개인풀 우선 전략**을 따릅니다. 다중 인스턴스 환경에서의 동시성 이슈를 원천 차단하기 위해 원자성(Atomicity)이 보장되는 **Redis Lua Script**를 활용합니다. + +![image.png](attachment:841655f0-0928-4f51-b914-361bd63563a5:image.png) + +![image.png](attachment:9aba6ad8-141a-4003-bbed-05d8dddb6a5a:image.png) + +1. **개인 데이터 우선 연산 (`INDIVIDUAL`):** 요청된 트래픽(예: 500MB)을 먼저 사용자의 개인 데이터 풀에서 차감 시도합니다. +2. **잔여량(Residual) 위임:** 개인 풀 잔여량이 부족해 `NO_BALANCE` 상태가 반환되면, 미처리된 잔여 트래픽을 계산합니다. +3. **가족 공유풀 보완 차감 (`SHARED`):** 미처리된 잔여 트래픽에 한하여 가족 공유 풀에서 추가 차감을 수행하여 결제/과금 누수를 방지합니다. +4. **알림 연동:** 공유 트래픽 차감 중 잔여량이 특정 임계치(Threshold) 아래로 내려가면, 비동기로 경고 알림(Alarm) 이벤트를 발행합니다. + +--- + +### **🛡 3. 완벽한 멱등성 보장 (Idempotency & Deduplication)** + +네트워크 지연이나 외부 시스템 재시도로 인해 동일한 이벤트가 여러 번 들어오더라도 **단 한 번만(Exactly-once)** 처리되도록 이중 방어 필터를 거칩니다. + +- **1차 필터 (In-Flight Dedupe):** Redis 연산을 통해 현재 실행 중인 트랜잭션의 `Trace ID`를 선점(Claim)합니다. 동시에 동일한 ID가 들어올 경우 병렬 실행을 차단합니다. +- **2차 필터 (Done Log DB):** 차감 성공 및 최종 상태(Final Status)는 고성능 MongoDB에 기록됩니다. 이미 처리 완료 지표(`Done Log`)가 존재하는 Trace ID라면 추가 연산 없이 바로 ACK 처리하여 스킵합니다. + +--- + +### **📊 4. 관측성 및 모니터링 (Observability)** + +복잡한 비동기 로직 내부를 투명하게 들여다보기 위해 철저한 로깅과 메트릭 수집을 진행합니다. + +- **MDC (Mapped Diagnostic Context) 기반 추적:** 워커 스레드 할당 시 `Trace ID`를 MDC에 주입하여 사이클 전체의 로그를 하나로 묶어 추적성을 확보합니다. +- **커스텀 TPS 및 Latency 메트릭:** 메시지가 폴링된 시점부터 최종 영속화(ACK)되기까지의 지연 시간(Latency)과 성공/중복 처리량 등을 Micrometer로 수집하여 Prometheus-Grafana 대시보드에 시각화합니다. + ### Monitoring image