Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 97 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,103 @@ Spring Boot 기반 API 서버로, Redis Stream 기반 메시지 처리와 Promet
### Infra
<img width="2760" height="1504" alt="image" src="https://github.com/user-attachments/assets/ec412e75-ad15-41f9-8062-e78d4dd43d2b" />

## 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
<img width="1024" height="559" alt="image" src="https://github.com/user-attachments/assets/dfca9e4b-c6cd-42bb-a0c4-018cec5bc577" />
Expand Down