티스토리 뷰
백프레셔는 Publisher
로부터 Subscriber
에게 끊임없이 전달되는 데이터를 안정적으로 처리하기 위한 처리 방식이다. 이러한 백프레셔를 좀 더 쉽게 이해하기 위해서는 Publisher
와 Subscriber
가 어떤 방식으로 데이터를 주고 받는지 이해하는 것이 좋다.
Publisher와 Subscriber간의 프로세스
리액티브 프로그래밍은 Publisher
와 Subscriber
간의 Interaction
이라고 볼 수 있다.
- 가장 먼저
Subscriber
에서subscribe()
메서드를 호출하면서 구독을 시작한다. Publisher
에서는 구독이 정상적으로 이루어졌음을onSubscribe signal
로subscriber
에게 알려준다.Subscriber
에서 데이터를 전달받기 위해request signal
을Publisher
에게 전송한다.Publisher
는 전달받은request signal
에 해당되는onNext signal
을Subscriber
에게 전송하면서 데이터를emit
한다.Subscriber
는Publisher
로부터 전달받은 데이터의 처리가 끝나면 다시request signal
을 전송하면서 데이터를 요청한다.Publisher
는 마찬가지로onNext signal
을Subscriber
에게 전송하면서 데이터를emit
한다.Publisher
쪽에서 더이상emit
할 데이터가 없으면 마지막으로onComplete signal
을Subscriber
에게 전달한다.
Backpressure
백프레셔는 Publisher
에서 emit
되는 데이터를 Subscriber
쪽에서 안정적으로 처리하기 위한 제어기능이다.
만약 Publisher
쪽에서 데이터를 하나 emit
했는데, Subscriber
쪽에서 처리하는 속도가 상당히 느리다고 가정해보자.Publisher
는 계속해서 데이터를 emit
하고 있지만, Subscriber
는 아직 1번 데이터를 처리하고 있다면 최악의 경우에는 처리하지 못한 데이터들이 쌓여 시스템 자체가 다운될 수 있다. 이처럼 리액티브 프로그래밍에서 들어오는 데이터를 안정적으로 처리하기 위해서는 백프레셔라는 기능이 필요하다.
Backpressure 전략
리액터에서는 백프레셔를 처리하는 방법으로는 Subscriber
가 적절히 처리할 수 있는 수준의 데이터 갯수를 Publisher
에게 요청하는 방식과 함께 다양한 전략을 제공한다.
Backpressure DROP 전략
DROP 전략이란, 버퍼가 가득 찼을 때 들어오는 데이터, Publisher
로부터 emit
된 데이터를 버퍼가 비워질 때까지 하나씩 DROP
되는 전략을 말한다.
public class BackPressureStrategyDropExample {
public static void main(String[] args) {
Flux
.interval(Duration.ofMillis(1L))
.onBackpressureDrop(dropped -> Logger.info("dropped: {}", dropped))
.publishOn(Schedulers.parallel())
.subscribe(data -> {
TimeUtils.sleep(5);
Logger.onNext(data);
},
Logger::onError
);
TimeUtils.sleep(2000);
}
}
- 버퍼가 가득찬 256번째 데이터부터
dropped
되는 모습을 확인할 수 있다.
Backpressure LATEST 전략
LATEST 전략이란, 버퍼가 가득찬 상태에서는 데이터가 폐기 되었다가 버퍼가 비워지는 시점에 emit
된 데이터 중에서 가장 최근에 emit
된 데이터부터 버퍼 안으로 들어오는 전략을 말한다.
public class BackPressureStrategyLatestExample {
public static void main(String[] args) {
Flux
.interval(Duration.ofMillis(1L))
.onBackpressureLatest()
.publishOn(Schedulers.parallel())
.subscribe(data -> {
TimeUtils.sleep(5);
Logger.onNext(data);
},
Logger::onError
);
TimeUtils.sleep(2000);
}
}
- 256번 데이터부터 폐기 되었다가 버퍼가 비워지는 시점에 가장 최근에
emit
된 1186번째 데이터부터 전달되는 모습을 확인할 수 있다.
Backpressure BUFFER DROP-LATEST 전략
BUFFER DROP-LATEST 전략이란, 버퍼가 가득차서 오버플로우가 발생했을 때, 가장 최근에 버퍼 안으로 들어온 데이터부터 DROP
되는 전략을 말한다.
public class BackPressureStrategyBufferDropLatestExample {
public static void main(String[] args) {
Flux
.interval(Duration.ofMillis(1L))
.doOnNext(data -> Logger.info("emitted by original Flux: {}", data))
.onBackpressureBuffer(2,
dropped -> Logger.info("Overflow & dropped: {}", dropped),
BufferOverflowStrategy.DROP_LATEST
)
.doOnNext(data -> Logger.info("emitted by Buffer: {}", data))
.publishOn(Schedulers.parallel(), false, 1)
.publishOn(Schedulers.parallel())
.subscribe(data -> {
TimeUtils.sleep(1000);
Logger.onNext(data);
},
Logger::onError
);
TimeUtils.sleep(2000);
}
}
- 오버플로우가 발생하자 가장 최근에 버퍼 안으로 들어온 5번 데이터가
DROP
되는 모습을 확인할 수 있다.
Backpressure BUFFER DROP-OLDEST 전략
BUFFER DROP-OLDEST 전략이란, 버퍼가 가득차서 오버플로우가 발생했을 때, 버퍼안의 데이터 중에서 가장 먼저 들어온(가장 오래된) 데이터부터 DROP
되는 전략을 말한다.
public class BackPressureStrategyBufferDropOldestExample {
public static void main(String[] args) {
Flux
.interval(Duration.ofMillis(1L))
.doOnNext(data -> Logger.info("emitted by original Flux: {}", data))
.onBackpressureBuffer(2,
dropped -> Logger.info("Overflow & dropped: {}", dropped),
BufferOverflowStrategy.DROP_OLDEST
)
.doOnNext(data -> Logger.info("emitted by Buffer: {}", data))
.publishOn(Schedulers.parallel(), false, 1)
.publishOn(Schedulers.parallel())
.subscribe(data -> {
TimeUtils.sleep(1000);
Logger.onNext(data);
},
Logger::onError
);
TimeUtils.sleep(2000);
}
}
- 버퍼안의 데이터 0, 1이
emit
되고, 오버플로우가 발생하자 가장 먼저 들어온 2번 데이터가DROP
되는 모습을 확인할 수 있다.
'Spring' 카테고리의 다른 글
[Spring Webflux] 컨텍스트 (Context) (0) | 2024.01.28 |
---|---|
[Spring Webflux] 스케줄러 (Scheduler) (0) | 2024.01.21 |
[Spring Webflux] Cold Sequence & Hot Sequence (0) | 2024.01.07 |
[Spring] 메트릭(metric)을 직접 등록해보자 (0) | 2023.04.17 |
[Spring] 프로메테우스 (prometheus) (0) | 2023.04.14 |
- Total
- Today
- Yesterday
- 북클럽
- 그리디
- webflux
- 김영한
- MySQL
- Algorithm
- 코틀린
- 릿코드
- 코테
- 구현
- 파이썬
- 스프링부트
- mysql 8.0
- 자료구조
- kotlin
- 스프링 부트
- leetcode
- 데이터베이스
- Real MySQL
- 리팩토링
- 노마드
- spring boot
- 스프링
- 문자열
- 인프런
- Spring
- 백준
- 알고리즘
- 노마드코더
- 정렬
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |