Skip to content

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

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

Projects

Status
Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions