Skip to content

[feat][queue-service] adaptive polling 도입 #34

@rlaxxwls13

Description

@rlaxxwls13

📌 개요

대기열 폴링 응답에 서버가 권장하는 다음 폴링 간격(retryAfterMs)을 포함하여 Server-driven Adaptive Polling 을 구현한다.

현재 클라이언트는 고정 3초 간격으로 폴링하고 있어 사용자 순번과 관계없이 동일한 부하를 발생시킨다. 부하 테스트 결과 1000 동시 사용자 기준 333 TPS 의 폴링 요청이 발생하며, 대부분 "아직 차례 아님" 응답인 비효율 구조다.

순번에 따라 폴링 간격을 차등 적용하여:

  • 임박한 사용자(≤100명): 빠른 알림 유지 (1초)
  • 멀리 있는 사용자: 폴링 간격 확대 (5~30초)

전체 폴링 부하를 약 40~50% 감소시키고, Thundering Herd 방지를 위해 jitter 를 함께 적용한다.

🎯 완료 기준

  • GET /api/v1/queues/programs/{programId} 응답 DTO 에 retryAfterMs 필드 추가
  • 사용자 순번에 따라 동적 계산된 retryAfterMs 값 반환
    • position ≤ 100: 1000ms (jitter 없음)
    • position ≤ 1000: 5000ms (jitter ±300ms)
    • position ≤ 10000: 15000ms (jitter ±500ms)
    • position > 10000: 30000ms (jitter ±4000ms)
  • ADMITTED 등 큐에서 빠진 상태(position = null)는 retryAfterMs = null 반환
  • @JsonInclude(NON_NULL) 로 null 값은 응답에서 제외됨 확인
  • nGrinder 부하 테스트 스크립트가 응답값 따라 동적 sleep 하도록 수정
  • Before/After 부하 테스트 비교 데이터 확보

🧩 작업 범위

  • QueueTokenResponse DTO 에 retryAfterMs 필드 추가
  • 순번 기반 폴링 간격 동적 계산 로직 구현
  • Jitter 적용 (ThreadLocalRandom)
  • nGrinder 폴링 스크립트 수정 (응답 파싱 → 동적 sleep)
  • Before/After 측정 및 비교

🏗️ 설계 요약

API 응답 변경

Before

{
  "tokenId": "...",
  "status": "WAITING",
  "issuedAt": "2026-05-19T...",
  "position": 234
}

After

{
  "tokenId": "...",
  "status": "WAITING",
  "issuedAt": "2026-05-19T...",
  "position": 234,
  "retryAfterMs": 5300
}

핵심 로직

QueueTokenResponse.from(QueueTokenResult result) 에서 result.position() 기반으로
retryAfterMs 동적 계산:

private static Integer calculateRetryAfterMs(Long position) {
    if (position == null) return null;
    
    int interval;
    int jitter;
    
    if (position <= 100)        { interval = 1000;  jitter = 0; }
    else if (position <= 1000)  { interval = 5000;  jitter = 300; }
    else if (position <= 10000) { interval = 15000; jitter = 500; }
    else                        { interval = 30000; jitter = 4000; }
    
    int jitterValue = jitter > 0 
        ? ThreadLocalRandom.current().nextInt(-jitter, jitter + 1)
        : 0;
    
    return interval + jitterValue;
}

변경 범위

  • 수정: presentation/dto/QueueTokenResponse.java (필드 추가 + 계산 로직)

🔗 참고 자료

  • 참고 자료 혹은 이미지 삽입 등이 필요한 경우, 이곳에 작성해주세요.

Metadata

Metadata

Assignees

Labels

No fields configured for Feature.

Projects

Status
Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions