WebFlux (2) - WebFlux 란 ? / SpringMVC vs WebFlux

김정욱·2021년 10월 27일
0

WebFlux

목록 보기
4/5
post-thumbnail

WebFlux 란 ?

[ 등장 배경 ]

  • Servlet의 변화
    • Servlet 3.0 에서 Async Servlet(비동기 서블릿) 개념 도입
      => 사용자의 요청을 받는 스레드(servlet thread)와 작업을 수행하는 스레드(worker thread)를 분리할 수 있게 되었다
    • Servlet 3.1 부터는 Non-Blocking I/O가 가능해졌다
      => request 및 response를 처리하는 I/O를 Non-Blocking으로 수행
    • 즉, Servlet의 변화로 SpringMVC에서 thread-per-request 방식인 기존 로직을 비동기 / Non-Blocking으로 개선할 수 있게 되었다
  • Blocking I/O를 통한 한계
    • Servlet의 API / Data Access / 추가 라이브러리 등 에서 결국 Blocking I/O가 수행
      => 100% 완전한 비동기 / Non-Blocking 을 위한 새로운 Stack 개발의 필요성
      => WebFlux라는 이름을 가진 Spring의 Reactive-Stack의 등장

[ 개념 ]

  • Spring의 reactive-stack web framework
  • Srpring5에서 새롭게 추가된 모듈

[ 특징 ]

  • Reactive library로 Project Reactor를 채택
  • 기본으로 Netty WAS 사용 => Event-Loop
  • 라우팅 / 핸들링 과정을 모두 함수형 엔드포인트로 사용 가능
  • Servlet 3.1+비동기 / non-blocking IO 사용
  • Servlet의 HttpServletReqeust / HttpServletResponse
    => ServerRequest / ServerResponse 로 대체

[ 목적 ]

  • 완벽한 Reactive-Stack을 통한 비동기 / non-blocking 개발
  • 적은 양의 스레드와 최소한의 하드웨어 자원으로 효율적인 동시성 핸들링(Concurrent Handling) 을 하는 것
    => How ?
    • Request를 Event-Driven 방식으로 처리
    • 비동기 / non-blocking I/O 사용

SpringMVC vs SpringWebFlux

[ Spring MVC ]

  • Servlet의 변화에 따른 thread model의 변화
    • Servlet 3.0 미만 : 동기 / 블록킹
    • Servlet 3.0 : 비동기 / 블록킹
    • Servlet 3.1+ : 비동기 / 논블록킹
      (상세 Task 처리에는 Bloacking이 존재할 수 있음)

[ Servlet 3.0 미만 ]

(ref :https://www.youtube.com/watch?v=I0zMm6wIbRI&t=721s)

  • 특징
    • 사용자의 요청마다 스레드가 필요한 Thread per request 방식 (동기 / 블록킹)
      => 보다 효율적인 사용을 위해 스레드 풀(thread pool) 사용
    • 스레드 풀의 스레드 수 이상의 요청이 오면 Blocking Queue에서 대기
      (Queue도 가득차면 오류 발생)
      => 동시성을 위한 대안으로, 단순히 스레드를 늘릴 수는 있다
      => 하지만, 무한정 늘릴수는 없다
      • 늘어난 스레드로 인한 많은 문맥교환(Context Switching) 비용과 메모리, CPU 부하 발생 위험 때문

[ 비동기 서블릿 - Servlet3.0 / 3.1 ]

  • Servlet 3.0
    • 최초 비동기 서블릿(Async Servlet)의 등장
    • 작업을 별도의 스레드에서 수행할 수 있게 되었다
      => 요청을 받는 Servlet Thread와, 처리하는 Worker Thread 로 분리
      (tomcat의 threadservlet thread를 의미)
    • 즉, 비동기 / 블록킹 방식의 thread model을 가지게 됨
      => servlet threadworker thread가 작업을 수행하는 동안 Blocking

(ref : https://www.youtube.com/watch?v=aSTuQiPB4Ns)

  • Servlet 3.1
    • Non-Blocking I/O 를 지원하게 되면서 더이상 servlet thread가 기다리지 X
      => servlet thread는 요청을 worker thread에게 할당 후 풀에 반납
      => worker thread의 작업이 끝나면 다시 servlet thread를 할당받아 response 수행
      => 비동기 / 논블록킹 방식
  • 한계
    • 사용자의 요청을 받고, 전체 Task 처리를 할당 측면에서는 비동기 / 논블록킹이 되었다
    • 하지만, 처리되는 세부적인 Task(DB access, api call) 내에서 Blocking API가 호출되면 결국 threadBlocking 된다
    • 즉, 완벽한 비동기 / 논블록킹의 로직을 만들기 위해서는 Blocking API가 없어야 한다는 것을 알 수 있다
      => WebFlux의 등장 배경

[ Servlet 3.2 - DeferredResult ]

(ref : https://www.youtube.com/watch?v=aSTuQiPB4Ns)

  • DeferredResult
    • 개념
      • 특정 이벤트에 반응해서 결과를 줄 때 유용하게 사용할 수 있는 기능
      • Servlet 3.2 에서 등장
    • 처리 흐름
      • 사용자의 request를 받아서 별도의 큐(DeferredResult Queue)에 저장
      • request를 받은 servlet thread는 풀에 반납
      • 특정 Event가 생겼을 때, servlet thread poolthread를 요청
      • servlet thread를 할당받고 작업을 수행한 뒤, 사용자에게 Response
    • 특징
      • 특정 Event가 발생했을 때 작업을 처리한다 => 이름처럼 지연된 결과
      • 별도의 worker thread를 생성하지 않는다
      • 작업 자체를 Event 기반으로 Reactive하게 처리
    • 한계
      • 완벽하게 Reactive하게 동작하는 비동기 / 논블록킹 방식을 구현하기에는 부족
        => DB 접근, API call 등 모든 부분이 논블록킹 방식으로 되어있어야 하기 때문
        => WebFlux의 필요성 !

[ Spring Webflux ]

  • 특징
    • Request를 Event-Driven 방식으로 처리 (기본 WAS가 Netty)
      => 사용자의 요청 / application 작업 모두 Event로 관리
      => Event QueueEvent가 쌓인다
      => Event Loop를 통해 순차적으로 처리
    • 요청을 받는 Thread가 Blocking되지 않는다
      => Context Switching이 적다
    • 결과적으로, 완전한 논블록킹으로 구성된다면,
      적은 Thread를 통해 많은 처리를 할 수있는 효율적인 모델을 구축할 수 있다
  • 주의
    • 오히려 Blocking I/O가 발생하면 SpringMVC에 비해 성능이 떨어질 수 있음
      => 상대적으로 적은 Thread Pool이기 때문
    • 논블록킹 Data Access를 사용해야 한다
      => JDBC 기반의 기술들(JPA 등)은 결국 모두 Blocking하게 동작
    • WebClient를 통한 논블록킹 api call이 필요하다
      => 기존의 RestTemplate은 기본적으로 Blocking하게 동작

refs

profile
Developer & PhotoGrapher

0개의 댓글