ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 이코에코(Eco²) Message Queue #13: Scan API 성능 측정 (SSE + Celery Chain + Gevent)
    이코에코(Eco²)/Message Queue 2025. 12. 25. 04:57

     

     
    Celery Chain + Gevent Pool 기반 비동기 아키텍처 전환 후 실제 성능을 측정하고, HTTP 1.1 + gRPC + asyncio와 비교합니다.

    항목 내용
    테스트 일시 2025-12-25 02:16 ~ 04:35 (KST)
    테스트 도구 k6 (JavaScript 기반 부하 테스트)
    대상 엔드포인트 /api/v1/scan/classify/completion (SSE)
    모니터링 Prometheus + Grafana (Scan SSE Pipeline 대시보드)

    1. 테스트 환경

    1.1 Queueing 아키텍처

    1.2 Worker 설정

    scan-worker gevent 100 1~5
    character-match-worker gevent 50 1~4
    character-worker gevent 50 1~2
    my-worker gevent 50 1~2

    1.3 k6 테스트 스크립트

    export const options = {
      stages: [
        { duration: "60s", target: 34 },  // 0 → 34 VU ramp-up
        { duration: "90s", target: 34 },  // 34 VU 유지
        { duration: "30s", target: 0 },   // ramp-down
      ],
      thresholds: {
        http_req_failed: ["rate<0.3"],       // 실패율 30% 미만
        sse_total_duration: ["p(95)<30000"], // 95%가 30초 이내
        sse_ttfb: ["p(95)<8000"],            // TTFB 95%가 8초 이내
      },
    };

    2. 테스트 결과

    2.1 테스트 케이스 요약

    1 02:16:01 ~ 02:17:45 10 100% 100% 링크
    2 02:59:01 ~ 03:00:12 34 82.8% 100% 링크
    3 04:31:59 ~ 04:34:45 30 95.1% 100% 링크

    k6 vs Grafana 불일치: k6에서 503 에러는 Istio/Envoy 레벨에서 no healthy upstream 발생.
    Grafana는 Celery 레벨 성공률 측정 → Worker가 처리한 Task는 100% 성공.


    2.2 테스트 #1: 저부하 (k6, VU 10, non-HA)

    Grafana 메트릭

    https://snapshots.raintank.io/dashboard/snapshot/QB6LdIZwjFLXiNVQq1xljAQ3vnVT77a3

    Chain Avg Duration 11.3s
    TTFB (p50) 1.74s
    Success Rate 100%
    RPS 0.10 req/s
    Active Connections (max) ~10

    스테이지별 평균 소요 시간:

    • vision: ~4.5s (OpenAI Vision API)
    • rule: ~0.3s (DB 조회)
    • answer: ~4.8s (OpenAI Chat API)
    • reward: ~1.7s (Character Match + DB)

    2.3 테스트 #2: 고부하 (k6, VU 34)

     
    Grafana 메트릭

    https://snapshots.raintank.io/dashboard/snapshot/ULL5FNeft8dN9yU25MYyKyEoOrMxbagk

    Chain Avg Duration 19.0s
    TTFB (p50) 1.07s
    Success Rate 90.7%
    RPS 1.10 req/s
    Active Connections (peak) 25

    문제 분석:

    1. 503 no healthy upstream: scan-api Pod가 과부하로 liveness probe 실패 → 재시작
    2. HPA가 스케일아웃 되기 전에 Pod 불안정 발생
    3. Celery Worker는 정상 처리 (Grafana Success 100%)

    2.4 테스트 #3: 안정화 (k6, VU 30)

    Grafana 메트릭

    https://snapshots.raintank.io/dashboard/snapshot/FqFEJTRNVC3G9SQbH0DWc2EluC7RlFzU
     

    Chain Avg Duration 21.1s
    TTFB (p50) 1.32s
    Success Rate 100%
    RPS 0.27 req/s

    관찰 사항:

    1. VU 30으로 감소 → 95.1% 성공률 달성
    2. p99 응답 시간이 ~25s로 증가 (OpenAI rate limit 근접)
    3. Reward Null 73.2%: 캐릭터 매칭 로직 이슈 (별도 수정 필요)

    3. 버전별 Scan API 성능표

    3.1 Scan API v1.0.0 (asyncio.to_thread, only HTTP 1.1)

    테스트 결과 (2025-12-08):

    5명 10s 15s 100%
    10명 11s 16s 100%
    100명 - 150s+ 0%

    병목 분석:

    • GIL로 인한 CPU 처리 병목
    • 스레드풀 크기 제한 (2+4 = 6 concurrent)
    • GPT I/O가 70~80% 점유

    3.2 /scan/classify (HTTP 1.1+gRPC, v1.0.7) vs /scan/classify/completion (SSE, v1.0.7)

    동시 처리 60명 (스레드 2+4, HPA 1-4), Success 98+% 30 greenlets (HPA 1-4), 100%
    평균 응답 시간 10~22초 11~21초
    성공률 98.3% 95.1% (50명 기준 성공률 38.7%)
    메모리 사용 4GB ~1GB (gevent)
    스케일링 HPA 자동 (1-4) HPA 자동 (1-4)
    병목 GIL + 스레드풀 SSE 연결 부하, Celery Task
    Grafana Snapshot p99 10-19.4s, avg 6s, CPU 0.04, Memory 174-300MB p99 49s, avg 13s, CPU 0.25, Memory 512MB+

    4. 핵심 지표 분석

    4.1 스테이지별 소요 시간

    vision 4.5s 6~10s 40% OpenAI Vision API
    rule 0.3s 2~3s 5% PostgreSQL 규칙 조회
    answer 4.8s 8~15s 45% OpenAI Chat API
    reward 1.7s 3~5s 10% 캐릭터 매칭 + DB

    소요 시간 비율:

           vision (40%)         rule(5%)      answer (45%)       reward(10%)
    ├────────────────────────────┼────┼─────────────────────────────┼───────┤
    │█████████████████████████████│████│█████████████████████████████│███████│
    └────────────────────────────────────────────────────────────────────────┘
    0s                          5s      6s                         11s     13s

    핵심 병목: OpenAI API 호출 (vision + answer)이 전체 소요 시간의 85% 차지.


    4.2 TTFB 분석

    저부하 (VU 10) 1.74s 5.7s 정상
    고부하 (VU 34) 1.07s 3.4s 빠름 (OpenAI 캐시 히트 추정)
    안정화 (VU 30) 1.32s 16.3s OpenAI 지연

    TTFB = 첫 번째 SSE 이벤트 도착 시간 (vision task 시작 시점)


    5. 개선 방향

    OpenAI 동기 호출 OpenAI Batch API (50% 비용 절감)
    Rate Limit 500 RPM Tier 업그레이드 or Multi-Provider
    scan-api HPA CPU 70% startupProbe 조정, 초기 replica 증가
    캐시 규칙 DB 조회 Redis 캐싱 (rule 단계 최적화)
    Celery Chain 동기식 Task Chain, 큐 부하 LangChain/LangGraph로 경량화, run_id 단위 큐잉

    6. 결론

    6.1 성과

    • prefork 대비 안정성: 30명 초과 부하에서 0% → 95% 성공률
    • 메모리 효율: 4GB → 1GB (75% 절감)
    • 자동 스케일링: HPA 기반 탄력적 확장

    6.2 한계

    • OpenAI Rate Limit: LLM IO 바운드가 상한, 보다 높은 Tier 혹은 멀티 프로바이더 재고
    • TTFB 증가: 부하 증가 시 p95 16s까지 상승
    • 큐잉 경량화 필요: LLM 체이닝을 Celery Chain으로 풀어 Task(동기) 및 큐잉 부하가 큼, LangChain/LangGraph로 경량화 필요
    • SSE 연결 부하 비용 높음: 기존 HTTP 1.1에 비해 스트리밍 방식인 SSE의 부하가 큶. 실시간 단계별 Event 전송으로 UX 상승 여력 존재.

    6.3 다음 단계

    1. OpenAI Batch API 적용 검토
    2. LangChain/LangGraph 마이그레이션 검토, run_id 단위로 큐잉 고려
    3. Rate Limit 대응 (Multi-Key 또는 Tier 업그레이드)

    관련 문서

    대시보드 정의

    • /backend/workloads/monitoring/dashboards/scan-sse-pipeline.yaml
    • /backend/workloads/monitoring/dashboards/domain-scan-api.yaml

    댓글

ABOUT ME

🎓 부산대학교 정보컴퓨터공학과 학사: 2017.03 - 2023.08
☁️ Rakuten Symphony Jr. Cloud Engineer: 2024.12.09 - 2025.08.31
🏆 2025 AI 새싹톤 우수상 수상: 2025.10.30 - 2025.12.02
🌏 이코에코(Eco²) 백엔드/인프라 고도화 중: 2025.12 - Present

Designed by Mango