개발기록

WebFlux에서의 순수 연산 작업: 워커 그룹 없이 처리하기 본문

카테고리 없음

WebFlux에서의 순수 연산 작업: 워커 그룹 없이 처리하기

Danuvibe 2024. 10. 15. 23:27

Spring WebFlux의 비동기, 논블로킹 모델은 I/O 집약적인 작업에 특히 효과적입니다.
그러나 순수한 연산 작업만 있는 경우, 이 모델은 어떻게 동작할까요? 이번 포스트에서는 이 주제를 깊이 살펴보겠습니다.

1. WebFlux의 스레드 모델 복습

WebFlux는 기본적으로 두 가지 주요 스레드 그룹을 사용합니다:

  1. 이벤트 루프 그룹 (또는 워커 그룹)
    • 역할: 모든 I/O 작업과 비동기 이벤트 처리
    • 구성: 여러 개의 이벤트 루프 스레드 (일반적으로 CPU 코어 수와 동일)
  2. Boss 그룹
    • 역할: 새로운 연결 수락
    • 구성: 일반적으로 1개의 스레드

2. 순수 연산 작업의 경우

순수한 연산 작업만 있는 경우에도, 이 작업은 이벤트 루프 그룹(워커 스레드)에서 처리됩니다.
Boss 그룹이 이러한 작업을 직접 처리하지 않습니다.

 

예를 들어:

@GetMapping("/compute")
public Mono<Integer> computeResult() {
    return Mono.fromSupplier(() -> {
        // 복잡한 연산 수행
        int result = 0;
        for (int i = 0; i < 1000000; i++) {
            result += i;
        }
        return result;
    });
}

이 예제에서는 순수한 CPU 연산만 수행하고 있습니다. 이 경우 이벤트 루프 스레드가 직접 이 작업을 처리합니다.

3. 이벤트 루프의 역할

이벤트 루프는 다음과 같은 역할을 수행합니다:

  1. 들어오는 요청 접수
  2. 비동기 작업 시작 및 관리
  3. 완료된 작업의 결과 반환

순수 연산 작업의 경우, 이벤트 루프가 직접 이 모든 과정을 처리할 수 있습니다.

4. 주의사항

그러나 주의해야 할 점이 있습니다:

  1. 긴 실행 시간: 연산 작업이 너무 오래 걸리면 이벤트 루프를 블로킹할 수 있습니다. 이는 전체 애플리케이션의 응답성을 저하시킬 수 있습니다.
  2. CPU 집약적 작업: 많은 CPU 자원을 사용하는 작업은 이벤트 루프의 성능을 저하시킬 수 있습니다.

5. 해결 방안

긴 실행 시간이나 CPU 집약적인 작업의 경우, 다음과 같은 방법을 고려할 수 있습니다:

  1. Schedulers.parallel() 사용:Schedulers.parallel()은 CPU 코어 수에 맞춰 최적화된 스레드 풀을 제공합니다.
  2. 작업 분할: 큰 작업을 더 작은 단위로 나누어 처리할 수 있습니다.
@GetMapping("/heavy-compute")
public Mono<Integer> heavyCompute() {
    return Mono.fromSupplier(() -> {
        // 무거운 연산 작업
        return heavyComputation();
    }).subscribeOn(Schedulers.parallel());
}

결론

순수 연산 작업만 있는 경우, WebFlux의 이벤트 루프만으로도 충분히 처리할 수 있습니다. 워커 그룹은 주로 I/O 작업을 위해 사용되므로, 이런 경우에는 필요하지 않습니다.

그러나 연산 작업이 복잡하거나 시간이 오래 걸리는 경우에는 이벤트 루프의 블로킹을 피하기 위해 Schedulers.parallel()과 같은 대안을 고려해야 합니다.

효율적인 WebFlux 애플리케이션을 만들기 위해서는 작업의 특성을 잘 이해하고, 적절한 처리 방식을 선택하는 것이 중요합니다.

Comments