대기열 구현 아이디어 V3

김형준·2025년 2월 26일
0

V2 방식의 문제점

결론적으로는 구현된 대기열의 여러 가지 사항(큐를 나눈 이유, 작업 큐를 비우는 방식을 스케줄러로 구현한 이유) 등에 대해 why?를 제대로 설명할 수 없다는 문제가 있음

  • 큐를 나눈 이유 부족
  • Reactor core & Redis 혼용
  • 스케줄러로 작업 큐에서 요청을 꺼내는 이유 부족
  • 큐 자료구조에 대한 고민 부족

그 외에도 기술적으로 문제가 있을 수 있는 부분들이 여럿 존재한다.

  • 대기 큐가 무한정 커질 수 있는 문제
  • 여러 scheduler들 간 잠재적인 race condition 문제
  • 현재 사용중인 JPA 드라이버가 동기적으로 작동하고 있는 문제

V3 개선점

  • 대기 큐 & 작업 큐를 하나로 합쳐 관리
  • 큐에서 요청을 꺼내 처리하는 작업을 스케줄러 대신 pub/sub을 활용하도록 수정
  • 큐는 기본적인 FIFO를 사용하는 자료구조로 수정
  • 대기열 처리를 위한 pub/sub 기술은 redis, kafka 등 외부 브로커 중 하나만 사용하도록 수정
    • 여러 메시지 큐들을 비교할 수 있도록 인터페이스를 분리할 것
    • 다른 메시지 큐 조사 및 도입은 Redis를 활용해서 구현한 이후 진행할 것
  • webflux 제거하기
    • 요청을 비동기적으로 처리해 스레드 당 효율을 높이는 것 자체는 좋음
    • 하지만 race condition 문제, callback 지옥, 잘못된 사용으로 인한 시스템 안정성의 저하, 까다로운 디버깅 등의 문제가 생길 여지가 있음
    • 따라서 요청을 동기적으로 처리하도록 수정할 예정
    • 다만 publisher/subscriber 스레드 간 데이터 공유 시에는 도입을 할 수도 있음

V3 기획

요청을 받는 스레드 측면

  1. 사용자가 Controller 계층에 요청을 전송한다.
  2. Controller에서는 publisher를 호출하는 QueueingService 메서드를 호출한다.
  3. QueueingService에서는 의존성이 분리되어 있는 메시지 발행 인터페이스를 통해 메시지를 발행한다.
  4. 이후 QueueingService에서는 consumer가 처리하는 요청 결과에 대해 일정 시간 동안 비동기적으로 대기한다.
    1. 일정 시간 동안 요청이 전송되지 않으면 timeout 예외를 던지도록 한다.
  5. 요청 처리 결과를 전송받으면 이를 Controller 측으로 넘겨 최종적으로 응답을 반환한다.

요청을 가져와 처리하는 스레드

  1. 애플리케이션 실행 시 같이 수행된 consumer 스레드에서는 큐에 값이 추가되었을 때 Redis로부터 신호를 받는다.
  2. Redis 신호 전송받은 경우 요청을 처리하고 결과를 publisher 스레드에 전송한다.

참고 사항

  • 두 스레드 간 데이터 공유 시에는 sinks를 활용할 예정
    • sinks를 보관하는 자료구조에서는 키값을 요청이 들어온 밀리초를 사용할 예정
  • 요청을 가져와 처리하는 스레드 수를 TaskExecutor를 통해 동적으로 조절할 수 있도록 할 예정

0개의 댓글

관련 채용 정보