spring에서 반응형 프로그래밍 지원을 위한 비동기 논블로킹 웹 프레임워크
reactive 스트림 사양을 기반으로 동작한다.
이벤트들을 비동기적으로 처리하며 이를 Publisher-Subscriber 패턴(Reactive Stream)으로 구현하며
한 스레드 내에서 요청에 대한 처리를 동기적으로 대기할 필요 없이 비동기적으로 다음 요청을 처리할 수 있다.
또한 확장성이 좋아 Spring MVC 및 다양한 서버(Netty, Undertow 등)과 통합 가능하다.
Reactor
reactive 프로그래밍 구현을 위한 데이터 스트림 기반의 pub-sub 구조를 갖는 Reactive 라이브러리
Event
Subscriber가 Publisher에 데이터를 요청, Publisher가 데이터를 생성 및 전송하는 과정
request(n) 메서드로 데이터를 요청할 수 있으며 onNext(data) 메서드로 Subscriber에 데이터를 전송한다.
BackPressure
subscriber가 처리 가능한 데이터의 양을 subscription을 통해 제어하는 것
이를 통해 publisher → subscriber 방향으로 subscriber가 처리 가능한 양의 데이터만 전송되도록 한다.
reactive 스트림 처리 과정
Mono
하나의 작업을 비동기적으로 처리 가능한 Publisher 클래스
작업 성공/실패에 대한 대기가 필요한 경우 적합하다.
메서드 이름 | 기능 |
---|---|
just() | 주어진 데이터를 포함하는 Mono 생성 |
empty() | 데이터가 없는 Mono 생성 |
error() | 에러 상황을 나타내는 Mono 생성 |
fromCallable() | Callable 객체를 이용해 Mono 생성 |
fromFuture() | Future 객체를 이용해 Mono 생성 |
fromRunnable() | Runnable 객체를 이용해 Mono 생성 |
Flux
여러 작업들을 동시에 처리 가능한 Publisher 클래스
데이터의 연속적 흐름, BackPressure가 필요한 경우 적합하다.
BackPressure를 지원하며, map(), filter(), flatMap() 등의 연산자로 데이터 스트림을 가공 가능
메소드 | 설명 |
---|---|
just() | 주어진 데이터를 포함하는 Flux 생성 |
fromIterable() | Iterable 객체를 이용해 Flux 생성 |
fromArray() | 배열을 이용해 Flux 생성 |
fromStream() | Stream을 이용해 Flux 생성 |
empty() | 데이터가 없는 Flux 생성 |
error() | 에러 상황을 나타내는 Flux 생성 |
range() | 지정된 범위의 정수를 포함하는 Flux 생성 |
interval() | 일정 시간 간격으로 값을 생성하는 Flux 생성 |
merge() | 여러 개의 Flux를 병합하여 하나의 Flux로 병합 |
concat() | 여러 개의 Flux를 순차적으로 이어붙여 하나의 Flux로 병합 |
zip() | 여러 개의 Flux를 조합하여 튜플 형태로 변환 |
collectList() | Flux에 포함된 모든 데이터를 리스트로 수집 |
collectMap() | Flux에 포함된 모든 데이터를 맵으로 수집 |
단일 스레드로 동작하는 이벤트 루프를 여러 개 사용해 동시에 많은 연결, 이벤트를 처리하는 아키텍처
이벤트 루프 내 많은 I/O가 발생해도 다른 루프를 통해 애플리케이션이 계속 동작할 수 있게 해 준다.
예시
아래와 같이 이벤트 루프 그룹들에 요청 수락 담당, I/O 작업 담당과 같은 역할을 분배할 수 있다.
EventLoopGroup bossGroup = new NioEventLoopGroup(1); // 연결 수락 전담
EventLoopGroup workerGroup = new NioEventLoopGroup(); // I/O 작업 처리 (CPU 코어 수 만큼)
Spring MVC는 요청을 처리하는 동안 스레드를 대기 상태로 있게 하는 블로킹 I/O 방식 → 요청 - 응답 및 각 작업들이 순차적으로 진행되도록 하며 요청과 스레드의 비율은 1:1 → 요청이 몰릴 경우 스레드를 많이 생성해야 하고 서버를 다운시킬 가능성이 높다.
WebFlux는 하나의 스레드 내에서 요청 처리 중인 경우에도 다음 요청을 바로 처리 가능 → 요청과 스레드의 비율을 1:1로 맞추지 않아도 된다.
예약 대기열 구현 시에 고려할 우선순위가 낮다고 판단되었다.
참고
https://adjh54.tistory.com/232