250722 5분 딸깍 이벤트 결과 보고서 ⏳ - 100-hours-a-week/5-yeosa-wiki GitHub Wiki
목적: 5분간 클릭 트래픽 폭주 대응 검증
클릭→앨범 생성: 20명 유저 → 992 앨범 생성 → 1,065개 이미지 분류
주요 시스템 반응
구성 요소 | 관측치 & 해석 |
---|---|
Spring Boot APM | • CPU 피크 60 % → 금세 10 % 회복• Hikari 풀 60→320 확장, Acquire ≤ 80 ms• Minor GC↑ but Stop‑the‑World ≤ 30 ms |
Cloud SQL (vCPU 1) | • CPU 100 % 포화·fsync 200 ops/s• 단일 vCPU 병목 확실 → 처리 지연 발생 |
Kafka 스트림 | • request 650 msg/min → 응답 처리 지연 (Lag 최대 1,040)• be‑group 컨슈머 스루풋 부족 |
GPU 서버 | • Util 최대 13 %, 대부분 idle → CPU 경로로 처리됨 |
총 20명의 유저가 992개의 앨범을 생성해 1065개의 이미지가 분류됨.
5분간(17:00 ~ 17:05) 실제 Kafka로 받은 요청과 처리 건수는 다음과 같습니다:
-
카테고리 분류:
- 요청 1,530건 ⇒ 응답 1,530건 (DLT 60건)
-
중복 검사:
- 요청 1,530건 ⇒ 응답 1,530건 (DLT 0건)
-
임베딩:
- 요청 2,110건 ⇒ 응답 2,100건 (DLT 39건)
-
인물 검출:
- 요청 1,530건 ⇒ 응답 1,530건 (DLT 0건)
-
품질 평가:
- 요청 1,540건 ⇒ 응답 1,530건 (DLT 0건)
-
스코어 계산:
- 요청 1,230건 ⇒ 응답 1,230건 (DLT 21건)
요약: 5분 동안 총 약 9,470건의 AI 요청이 들어와 9,450건(99 %)을 실시간 처리했고, DLT로는 120건(1.3 %) 이 넘어갔습니다.
- DB vCPU 확장 (1→2+) & 슬로 쿼리 인덱싱
- Kafka 파티션 2→6+ & be‑group 오토스케일
- Hikari 최소 Idle 조정 (워밍업)
- GPU 배치·스레딩 최적화
- 모니터링 강화 (Kafka exporter, P95/P99, Lag 알람)
결론:
5분간 대부분 컴포넌트가 1 ∼ 2분 내에 정상 회복했으나, 단일 vCPU DB와 Kafka 소비 병목이 드러났습니다. 위 개선안을 적용하면 다음 이벤트에서 보다 안정적인 처리 성능을 확보할 수 있습니다.
대시보드 열기

핵심 구간 — 17 시 00 분 ~ 17시 05분
시각 | 지표 변화 | 해석 |
---|---|---|
16:58 ~ 17:00 | • CPU 5 % → 30 %• Open File FD ≈ 200 → 600 | 워밍‑업 트래픽 & Keep‑Alive 활성 |
17:00 : 15 | CPU 피크 ≈ 60 % Load Avg 7.5Heap Eden Usage 급등 | 동시 요청·스레드 수 크게 증가, 아직 시스템 여유 |
17:01 | • Hikari Connection Size 60 → 320 (풀 최대)• Acquire Time 최고 80 ms | 풀 고갈 직전 → 즉시 신규 커넥션 생성 |
17:02 | • Minor GC 집중 (30 회/min)• Old Gen 증가 없음 | 대량 객체 일시 생성, Stop‑the‑World 미미(≤ 30 ms) |
17:03 | CPU 30 % → 10 %, Load Avg 하락 | 요청 정점 통과, GC 완료 |
17:04 ~ 17:05 | 모든 지표 평상시(Heap 11 %, CPU < 5 %) 회귀 | 이벤트 종료, 리소스 정상화 |
카테고리 | 관찰값 | 의미 / 병목 여부 |
---|---|---|
CPU | - 최대 70 % (4 vCPU 가정 시 한 코어 포화) - 3개의 인스턴스 모두 50 ~ 75 % 사이에서 짧게 치고 내려왔고 평균은 15 % 미만이므로, 현재 LB‑전략으로 부하 분산은 양호 |
여유 있음 — CPU 바운드 아님 |
Load Average | 최대 ≈ 8 | 스레드(대기+실행) 급증, 커넥션 풀 확장과 연계 |
Heap / GC | Eden 스파이크 → Minor GC 다발, Old Gen 안정 | GC 튜닝 불필요, 메모리 누수 없음 |
HikariCP | Total 320, Active ≤ 70, Acquire Time ≤ 80 ms | 풀 크기 자동 확장은 상승세 제어, DB 병목 없음 |
Open Files | 600 → 200 | 워커 & keep‑alive 소켓 증가 후 정리 |
Threads | 20 → 70 | 비동기 과제 작업·Netty 이벤트루프 활성 |
HTTP/Request 패널 | 데이터 없음 (미계측) | histograms 비활성 ⇒ P95 Latency 분석 불가 |
- 용량 : CPU 40 % 여유, Heap 88 % 여유 → 두 배 이상 트래픽도 현재 스펙으로 수용 가능.
- DB 커넥션 풀 : 이벤트 순간 Total 320 까지 증가했지만 Acquire Time < 100 ms → 정상. minimumIdle 30 정도로 워밍‑업하면 초기 대기 더 줄일 수 있음.
개선사항
-
관측 가능성 강화 :
management.metrics.distribution: percentiles-histogram.http.server.requests: true percentiles.http.server.requests: 0.95,0.99
히스토그램 활성 후 P95 Latency / Success Rate 패널 & Alert 추가 권장.
17 시 이벤트는 CPU 60 %, 커넥션 풀 자동 확장, Minor GC 증가로 3 분 내 안정적으로 처리됐으며, 시스템 자원은 충분합니다.
대시보드 열기

로컬 시각(KST) | 지표 변화 | 해석 |
---|---|---|
04 : 58 | CPU 10 % → 35 % 상승 | 백로그 워밍‑업 |
05 : 00 | CPU 100 % 포화Rows Read ≈ 350 MB/min, Write ≈ 90 MB/min | 단일 vCPU 한계 도달, 완전 CPU‑바운드 |
05 : 01 | InnoDB fsync(Data·Log) 200 ops/s 피크 | 커밋마다 플러시 → 추가 CPU 소모 |
05 : 02 | CPU 60 % ↓, fsync 하락 | 트래픽 정점 통과 |
05 : 03‑04 | CPU 40 % → 15 %, Rows Read/Write 급감 | 처리 완료, Idle 상태 회복 |
05 : 05 | 모든 지표 평상시 (CPU ≤ 5 %, fsync≈0) | 이벤트 종료 |
카테고리 | 값 | 의미 / 병목 |
---|---|---|
CPU | P99 = 100 % | vCPU 1 인스턴스 한계, 진정한 병목 |
Disk Busy | 1.3 % | I/O 여유, 디스크 병목 아님 |
Rows Read / Write | 350 MB/min Read, 90 MB/min Write | 읽기 위주 트래픽, 캐시 탑재 성공 |
Buffer Pool 적중률 | 98 % → 99 % 로 향상 | 캐싱 OK, 디스크 페이지 미미 |
Slow Log | 1 건 200 s 슬로 쿼리 | 인덱스 누락 or filesort 가능성 |
Connections | < 2 conn/s | 풀·커넥션 병목 X |
한줄요약: 이벤트 이전에 CloudSQL CPU 성능을 향상할 필요가 있습니다.
대시보드 열기


초당 레코드 수

컨슈머 그룹별 파티션 lag 총합

각 토픽의 파티션 개수
- 7 월 22 일 16 : 40 ~ 18 : 00 (KST) 트래픽/지연 분석
토픽 | 생산 속도 (Max msg/s) | 주요 소비 그룹 | 소비 속도 (Max msg/min) | 파티션 수 |
---|---|---|---|---|
album.ai.*.request 6종 |
8 ~ 11 msg/s (≈ 650 msg/min) |
ai‑*‑group (AI 워커) |
422 msg/min (ai‑embedding-group ) |
2 |
album.ai.*.response 6종 |
8 ~ 9 msg/s |
be‑group (백엔드) |
1 040 msg/min (be‑group category) |
2 |
album.ai.*.response.DLT 6종 |
≤ 0.25 msg/s | debug‑group | 7 msg/min (debug-group ) |
2 |
__transaction_state |
171 msg/s (6.9 K/min) | 브로커 내부용 | 내부 브로커 트래픽 | 50 |
16 : 55 ~ 17 : 10 구간에 __transaction_state 가 가장 많은 메시지를 기록하지만, 이는 Kafka 트랜잭션 메타‑로그이며 애플리케이션 병목과 직접 연관되지는 않습니다.
Consumer Group | 최대 Lag | 잔여 Lag(18 : 00) | 관찰 |
---|---|---|---|
be‑group – category.response |
1 040 | 784 | 17 : 05에 최대치, 이후 1 msg/s 미만 속도로만 감소 → 완전히 못 빼고 있음 |
be‑group – embedding.response |
641 | 0 | 17 : 12에 해소 |
be‑group – quality.response |
444 | 242 | 아직 절반 미처리 |
ai‑*‑group (request 토픽) |
≤ 61 | 2 | AI Worker 쪽은 실시간 처리 |
debug‑group (DLT) |
1 K | 0 ~ 1 | Dead‑Letter 큐는 슬로우하지만 영향 작음 |
원인 요약
-
Response 토픽을 읽는
be‑group
처리 스루풋 부족 → Back‑pressure로 Lag 폭증 - 토픽 파티션이 2 개뿐이라 소비 병렬도 한계 (각 파티션당 1 스레드)
-
quality.response
·score.response
계열은 CPU‑바운드 후처리(스코어 계산, DB write 등) 로 추정 – Drain 속도 느림
시각 | 메시지/sec | Lag 증가 | 해석 |
---|---|---|---|
16 : 45 | request 토픽 폭주 시작 (green peaks) | Lag 0 → 200 | AI Workers 정상 소비 |
17 : 00 | response 토픽 생산량 ↑ | be‑group Lag 0 → 1 040 |
BE 서버 처리 한계 → Back‑pressure |
17 : 05 | 생산량 하락 | Lag 고점 유지, 이후 완만히 감소 | 비동기 Drain 단계 |
17 : 45 | Lag 여전히 500 이상 (category.response ) |
1 msg/s 미만 속도로만 줄어듦 | 처리 속도 개선 필요 |
신호 | 추정 병목 |
---|---|
Lag 급증 ↔ consume 속도 200 msg/min 이하 |
be‑group 컨슈머 인스턴스 수나 스레드 수 부족 |
파티션 2 개 고정 | 컨슈머를 늘려도 파티션이 병목 |
DLT 메시지 거의 없음 | 실패율 원인은 아님, 순수 처리량 이슈 |
__transaction_state 폭주 | 프로듀서의 트랜잭션 사용; 브로커 성능엔 큰 영향 X |
우선순위 | 조치 | 기대 효과 |
---|---|---|
⭐ 1. Response 토픽 파티션 2 ➜ 6~10 | 소비 병렬도 3‑5 배 ↑ → Lag 급증 억제 | |
⭐ 2. be‑group 컨슈머 인스턴스 / 스레드 Autoscale |
HPA → Lag > 100 시 2 → 6 Pod 확장 | |
3. Batch 처리 | response 레코드 50‑100 개씩 Bulk‑DB insert → 처리/IO 효율 ↑ | |
4. 모니터링 알람 |
kafka_consumergroup_lag{group="be-group"} > 500 FOR 2m → Slack WARN |
|
5. 트랜잭션 OFF (선택) | idempotent producer + exactly‑once 미사용 시 Tx disabled → __transaction_state 트래픽 ↓ |
한 줄 요약: 17 시 이벤트에서 “request → response” 처리 파이프라인이 request 측보다 느려 be‑group Lag 최대 1 K 누적, 이후 30 분이 지나도 절반 이상 잔존했습니다.
파티션 확장 + 컨슈머 오토스케일 + 배치 Write 로 “응답 스트림 처리량을 요청 스트림과 맞추는 것”이 가장 시급합니다.
대시보드 열기

구간 | 최대 Util (%) | 지속 시간 | 특징 |
---|---|---|---|
16 : 30 ~ 16 : 56 | ≈ 0 | 26 분 | GPU idle – 폴링·헬스체크만 발생 |
① 16 : 58 ~ 17 : 05 | 13 % (17 : 01) | ~7 분 | 이벤트 메인 배치Util 5 → 13 % → 0 % 로 급등·급락 |
17 : 05 ~ 17 : 24 | 0 ~ 1 % | 19 분 | 사실상 idle |
② 17 : 25 | 5 % | < 1 분 | 단발성 마이크로 배치 |
17 : 26 ~ 17 : 54 | ≈ 0 | 28 분 | idle |
③ 17 : 55 ~ 17 : 59 | 4 ~ 5 % | ~4 분 | 잔여 요청 처리 배치 |
한 줄 요약: 이벤트 기간에도 GPU는 최대 13 %만 쓰였습니다. 배치 사이즈·오토스케일링을 조정해 Util ≥ 50 % 로 끌어올리면 같은 GPU로 더 많은 요청을 소화할 수 있습니다.