Programming/Error

block()/blockFirst()/blockLast() are blocking, which is not supported in thread reactor-http-nio-3

Jan92 2021. 12. 28. 23:28

block()/blockFirst()/blockLast() are blocking, which is not supported in thread reactor-http-nio-3

 

WebClient 사용법을 학습하던 중 발생한 오류입니다.

 

WebClient는 비동기식 웹 애플리케이션 구축을 위한 WebFlux의 기능 중 일부로 RestTemplate 클라이언트를 대체하는 새로운 API이며, 비차단 및 반응 웹 클라이언트입니다.

(Blocking 또는 Non-Blocking HTTP 요청을 모두 만들 수 있으며 Spring5 릴리즈 이후로 권장되는 방식입니다.)

 

 

  public ResponseEntity<?> getTest() {
    ResponseSpec responseSpec = webClient.mutate().build()
        .get()
        .uri("http://localhost:8082/webServer/get")
        .retrieve();

    ResponseEntity<User> result = responseSpec.toEntity(User.class).block();
    return ResponseEntity.ok(result);
  }

오류가 발생한 코드입니다.

.bodyToMono() 메서드를 사용하여 Mono<> 타입으로 결과를 받아올 때는 이상 없이 작동하던 코드가 .block() 메서드를 사용하는 부분에서 오류가 발생하였습니다.

 

이유는 bodyToMono() 메서드는 논블로킹(Non-Blocking)으로 동작하는 반면, block() 메서드는 블로킹(Blocking)으로 동작하는데 에러 메시지처럼 작동하고 있는 Thread는 블로킹(Blocking)을 지원하지 않는다는 것입니다.

 

 

blockingGet()

오류가 발생한 blockingGet() 메서드입니다. 첫 번째 if 문의 isInNonBlockingThread() 메서드를 통해 작동하고 있는 스레드가 NonBlocking Thread인지 여부를 확인하여 해당 Exception을 던지고 있습니다.

 

 

 

    // https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web
    implementation group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '2.6.1'

해당 오류에 대한 해결 방법은 'spring-boot-starter-web' 의존성을 추가하는 것입니다.

 

 

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter'
    implementation 'org.projectlombok:lombok:1.18.18'
    annotationProcessor('org.projectlombok:lombok')
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    
    // spring-boot-starter-web 의존성 추가
    // https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web
    implementation group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '2.6.1'
    
    // https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-webflux
    implementation group: 'org.springframework.boot', name: 'spring-boot-starter-webflux', version: '2.6.1'
}

(의존성 추가 후)

 

 

Netty

기존 'spring-boot-starter-webflux' 의존성만 추가되었을 때는 Non-Blocking 기반의 Netty가 동작하여 [ctor-http-nio-3] 라는 이름의 스레드가 동작하는 반면에

 

tomcat

'spring-boot-starter-web' 의존성을 추가했을 때는 Tomcat으로 실행되며 [nio-8081-exec-2] 라는 이름의 스레드가 실행됩니다.

 

 

결론적으로 WebClient를 블로킹(Blocking) 형식으로 사용하고 싶다면 블로킹을 지원하는 스레드 환경에서 작동시켜야 하는 것 같습니다.

 


 

 

WebClient 사용법 학습 중 발생한 오류로 아직 개념 및 사용법을 익히는 중입니다. 때문에 부족한 내용이나 잘못된 부분이 있을 수 있습니다. 해당되는 부분이 있다면 댓글 남겨주시면 확인 후 수정하겠습니다. 미리 감사드립니다.

 

 

 

 

< 함께 보면 좋은 자료 >

 

동기와 비동기, 블로킹과 논블로킹 개념 정리

'동기와 비동기, 블로킹과 논블로킹 - 비슷한 듯하면서도 비슷하지 않은 개념들' 프로그래밍을 하며 자주 접하게 되는 단어들이지만 개념적으로 명확하게 차이를 짚고 넘어간 적이 없었는데 이

wildeveloperetrain.tistory.com

 

스프링 프레임워크 Reactive Stack, Servlet Stack 개념

'스프링 프레임워크(Spring Framework) Reactive Stack과 Servlet Stack' WebClient를 사용하기 위해서 공부하던 중 WebFlux의 개념과 더불어 함께 공부하게 된 부분입니다. 전체적인 Reactive Programming과 함께..

wildeveloperetrain.tistory.com