본문 바로가기

학습/WebFlux

Scheduler

📚 이전학습

Scheduler 📘

Thread에 대한 이해 🧵

Thread의 기본 개념

  • 정의: 프로세스 내에서 실행되는 가장 작은 실행 단위
  • 특징: 독립적인 실행 경로와 스택을 가짐
  • 동시성: 여러 작업을 동시에 처리 가능

Thread의 종류

  1. User Thread (사용자 스레드)
    • 애플리케이션 레벨에서 생성/관리
    • 개발자가 직접 제어 가능
  2. Daemon Thread (데몬 스레드)
    • 백그라운드에서 실행

데몬 스레드는 백그라운드에서 동작하며, 주요 애플리케이션의 동작에 영향을 미치지 않고 보조 작업을 수행합니다.

    • 백그라운드에서 실행
      • 데몬 스레드는 메인 스레드가 종료될 때 자동으로 종료됩니다. 즉, 명시적으로 종료 시키지 않아도 됩니다.
    • 자동종료
      • 데몬 스레드는 메인 스레드가 종료될 때 자동으로 종료됩니다. 즉, 명시적으로 종료 시키지 않아도 됩니다.

출저: https://javarevisited.blogspot.com/2012/03/what-is-daemon-thread-in-java-and.html#axzz8tEnE1zcC

Scheduler 기본 개념 ⚙️

정의와 목적

  • 정의: Reactor의 비동기 실행 흐름을 제어하는 핵심 컴포넌트
  • 목적: 작업의 실행 컨텍스트와 타이밍을 효율적으로 관리
  • 역할: 리액티브 스트림의 처리 위치와 방식을 결정

핵심 특징 🎯

  1. 비동기 처리 최적화
    • 논블로킹 작업 실행
    • 효율적인 리소스 활용
    • 높은 처리량 보장
  2. 스레드 관리 시스템
    • 자동화된 스레드 풀 관리
    • 작업 부하의 균등한 분산
    • 스레드 생명주기 자동화
  3. 컨텍스트 관리
    • 유연한 실행 컨텍스트 전환
    • 상황별 최적 실행 환경 제공
    • 효율적인 리소스 스케줄링

Scheduler 타입 가이드 �

1. Schedulers.immediate() ⚡

  • 언제 사용하나요?
    • 간단하고 빠른 작업이 필요할 때
    • 스레드 전환이 필요 없는 경우
    • 최소한의 오버헤드가 필요한 경우
  • 장점
    • 즉각적인 실행
    • 추가 리소스 사용 없음
    • 간단한 구현
// 간단한 숫자 출력 예시
Flux.just(1, 2, 3)
    .subscribeOn(Schedulers.immediate())
    .subscribe(num -> System.out.println("처리된 숫자: " + num));

2. Schedulers.single() 🎯

  • 언제 사용하나요?
    • 순서가 중요한 작업을 처리할 때
    • 단일 스레드로 충분한 경우
    • 동시성 문제를 피하고 싶을 때
  • 장점
    • 순차적 실행 보장
    • 예측 가능한 동작
    • 리소스 효율적 사용
// 순차적 데이터 처리 예시
Flux.range(1, 5)
    .publishOn(Schedulers.single())
    .map(num -> "처리 순서: " + num)
    .subscribe(System.out::println);

3. Schedulers.boundedElastic() 🌊

  • 언제 사용하나요?
    • 데이터베이스 작업
    • 파일 입출력
    • API 호출
    • 블로킹 작업이 필요한 경우
  • 장점
    • 효율적인 리소스 관리
    • 작업 대기열 제공
    • 블로킹 작업에 최적화
// API 호출 예시
Flux.fromIterable(apiUrls)
    .flatMap(url -> Mono.fromCallable(() -> callExternalApi(url))
                        .subscribeOn(Schedulers.boundedElastic()))
    .subscribe(response -> System.out.println("API 응답: " + response));

4. Schedulers.parallel() 💪

  • 언제 사용하나요?
    • 대량 데이터 처리
    • 복잡한 수학 계산
    • CPU를 많이 사용하는 작업
  • 장점
    • 최대 CPU 활용
    • 병렬 처리 최적화
    • 높은 처리량
// 대량 데이터 병렬 처리 예시
Flux.range(1, 1000)
    .parallel()
    .runOn(Schedulers.parallel())
    .map(num -> complexCalculation(num))
    .subscribe(result -> System.out.println("계산 결과: " + result));

Scheduler 선택 가이드 🤔

Scheduler 타입 최적의 사용 사례 주의사항
immediate() 간단한 동기 작업 블로킹 작업 피하기
single() 순차적 처리 필요 작업 긴 작업은 피하기
boundedElastic() I/O 작업, 블로킹 작업 스레드 수 제한 확인
parallel() CPU 집약적 작업 메모리 사용량 주의

모범 사례 및 주의사항 ⚠️

1. 스레드 안전성 확보

  • 공유 상태 접근 시 동기화 메커니즘 사용
  • 불변 객체 활용
  • 부작용이 있는 연산 주의

2. 리소스 관리

  • 적절한 스케줄러 선택
  • 리소스 해제 보장
  • 메모리 누수 방지

3. 성능 최적화

  • 불필요한 스케줄러 전환 최소화
  • 적절한 배압(Backpressure) 전략 사용
  • 모니터링 및 튜닝

4. 디버깅 팁

  • 로깅을 통한 스레드 추적
  • 스케줄러 동작 검증
  • 성능 병목 지점 식별

예제소스 📖

Scheduler Operator 예제

Parallel 처리 예제

Schedulers 타입별 예제


참고자료 📚

공식 문서

추천 도서

  • "Hands-On Reactive Programming in Spring 5.0" - Oleh Dokuka
  • "Reactive Programming with Java and Spring" - Josh Long

유용한 온라인 자료

커뮤니티 리소스


🔗 GitHub Repository



자세한 학습 자료는 아래 GitHub 저장소를 참조하세요:
https://github.com/ses9892/learn_recator_programing/tree/main

'학습 > WebFlux' 카테고리의 다른 글

생성형 Operator - API  (0) 2024.12.03
Context  (1) 2024.12.02
Sinks  (0) 2024.11.28
Backpressure  (0) 2024.11.27
Recactor 용어정의  (1) 2024.11.26