Be-Developer

Webflux thread

mono/flux 에서 block시 데드락이 걸리는현상을 개선중, controller로 mono/flux가 직접 반환될때, 그럼 api요청을 받은 스레드와 webclient에서 생성한 스레드가 둘다 생길텐데, api 요청을 받은 스레드는 먼저 종료되는것인가?

return Mono.just

    @GetMapping("/v1/delay-test")
	public Mono<String> delay(@RequestParam int delaySeconds) {
		log.debug("out of mono");
		return Mono.just("ok")
			.map(t -> {
				log.debug("in mono");
				return t;
			})
			.delayElement(Duration.ofSeconds(delaySeconds));
	}

api 응답이 mono이고, 일반 mono를 생성하여 그대로 리턴할때, 같은 스레드에서 동작된다.

[     parallel-1] Created new WebSession.
[     parallel-1] out of mono
[     parallel-1] in mono

return Webclient.bodyToMono()

    @GetMapping("/v1/delay-test")
	public Mono<String> delay(@RequestParam int delaySeconds) {
		Thread thread = Thread.currentThread();
		log.debug("out of mono, thread : {} , {}", thread.getName(), thread.isAlive());
		return WebClientUtil.get("http://test.com", 5)
			.get()
			.uri("/test/api")
			.retrieve()
			.bodyToMono(String.class)
            .delayElement(Duration.ofSeconds(10))
			.map(t -> {
				log.debug("in mono: {} , {}", thread.getName(), thread.isAlive());
				Thread thread2 = Thread.currentThread();
				log.debug("in mono: {} , {}", thread2.getName(), thread2.isAlive());
				return t;
			});
	}

webclient 에서 새로운 스레드를 할당받는데, 그렇다고 기존 세션스레드가 사라지는것은 아니다. ㄴ 그럼 Accept: text/event-stream , Accept: application/stream+json 으로 요청시 먼저오는 응답은 먼저받을수있다는 장점 빼고는?

[     parallel-1] Created new WebSession.
[     parallel-1] out of mono, thread : parallel-1 , true
[ctor-http-nio-4] [842502c8] Connecting to xxx.
[ctor-http-nio-4] in mono: parallel-1 , true
[ctor-http-nio-4] in mono: reactor-http-nio-4 , true
[ctor-http-nio-4]  Releasing channel

subscribe

    @GetMapping("/v1/delay-test")
	public Mono<String> delay(@RequestParam int delaySeconds) {
		Thread thread = Thread.currentThread();
		log.debug("out of mono, thread : {} , {}", thread.getName(), thread.isAlive());
		WebClientUtil.get("http://test.com", 5)
			.get()
			.uri("/test/api")
			.retrieve()
			.bodyToMono(String.class)
			.delayElement(Duration.ofSeconds(10))
			.map(t -> {
				log.debug("in mono: {} , {}", thread.getName(), thread.isAlive());
				Thread thread2 = Thread.currentThread();
				log.debug("in mono: {} , {}", thread2.getName(), thread2.isAlive());
				return t;
			})
			.subscribe(s -> log.debug("end!!"));

		return Mono.just("result");
	}   

api는 먼저 종료되어 응답이 먼저 나가고, subscribe 는 이후에 따로 처리된다. 스레드는 종료까지 살아있다.

[     parallel-1] Created new WebSession.
[     parallel-1] out of mono, thread : parallel-1 , true
[ctor-http-nio-4] [4bd9880f] Created a new pooled channel,
[     parallel-1] [7ee538f9-1] Writing "result"
[ctor-http-nio-4] [4bd9880f] Releasing channel
... 10s 뒤
[     parallel-2] in mono: parallel-1 , true
[     parallel-2] in mono: parallel-2 , true
[     parallel-2] end!!

for loop Mono vs Flux.flatMap

forloop 에서 mono를 호출하는것과 Flux.flatmap 에는 사용하는 스레드의 차이가있을까 flux는 하나의 스레드에서 처리되지않을까?

forloop로 webclientMono를 호출시

	private Mono<String> mono(String prefix, int i) {
		return webClient.get()
			.uri("/test-call")
			.retrieve().bodyToMono(String.class)
			.doOnNext(index -> log.error(prefix + " " + i + ": thread {} ", Thread.currentThread().getName()))
			.delayElement(Duration.ofMillis(300));
	}

	
	// 테스트 대상
	for (int i = 0; i < 10; i++) {
		mono("mono", i).subscribe();
	}
mono 3: thread reactor-http-nio-7 
mono 2: thread reactor-http-nio-6 
mono 6: thread reactor-http-nio-2 
mono 5: thread reactor-http-nio-1 
mono 1: thread reactor-http-nio-5 
mono 0: thread reactor-http-nio-4 
mono 4: thread reactor-http-nio-8 
mono 9: thread reactor-http-nio-5 
mono 8: thread reactor-http-nio-4 

스레드풀에서 반복횟수만큼 꺼내서 쓴다

flux.flatmap으로 webclientMono 호출시

	Flux.fromStream(IntStream.range(0, 10).boxed())
		.flatMap(i -> mono("flux", i))
		.subscribe();

결과

flux 6: thread reactor-http-nio-6 
flux 1: thread reactor-http-nio-1 
flux 0: thread reactor-http-nio-8 
flux 5: thread reactor-http-nio-5 
flux 3: thread reactor-http-nio-3 
flux 4: thread reactor-http-nio-4 
flux 2: thread reactor-http-nio-2 
flux 7: thread reactor-http-nio-7 
flux 8: thread reactor-http-nio-8 
flux 9: thread reactor-http-nio-1 

차이가 없다.