본문 바로가기
Programming/Spring

[리액티브 프로그래밍] WebFlux의 동시성

by peter paak 2021. 3. 25.
728x90

Thread per request 모델

  • 스레드 하나당 하나의 요청을 처리
    • 멀티 코어 환경에서 여러개의 스레드가 여러개의 요청을 처리할 수 있다
  • 단점
    1. 하지만 하나의 요청(스레드)이 한시간 짜리 IO를 만나게 되면 여전히 block된다.
    2. 자바에서 사용하는 native 스레드는 context switching(스레드간 스위칭)할 때 비용이 매우 크다
    3. 요청이 많아지게되면 thread per model을 효율적이지 않다.

Reactive Programming 모델

  • data flow(데이터 흐름)와 propagation(전파)를 사용한다
    • 완전한 non blocking 환경을 보장한다
    • 기존의 방법과 다른 스레드 사용법을 이용한다

  • 데이터베이스에게 read 요청을 보내면, 데이터를 가져오는 동안 스레드를 block하지 않는다
  • 요청은 Publisher를 바로 반환하여 다른 Subscriber가 subscribe 할 수 있다
  • Subscriber는 다른 네트워크나 데이터베이스 이벤트를 처리할 수 있다.
  • 정리하면 어떤 스레드 이벤트가 생성되거나 소비되는지 특정하지 않는다
    • 데이터베이스를 읽는 이벤트를 요청하고 데이터베이스 데이터를 받아오는 동안 데이터를 쓰는 이벤트를 처리할 수 있다.
    • 데이터 읽기가 끝나면 다른 Publisher가 해당 이벤트를 처리할 수 있다.

Event Loop

  • 서버의 비동기 프로그래밍 모델은 Event Loop를 사용한다
  • Event Loop는 하나의 스레드에서 계속 돈다
    • 물론 CPU 코어에 따라 여러개의 Event Loop를 돌릴 수 있다
  • 이벤트를 이벤트 큐에서 순차적으로 대기하고 플랫폼에 콜백이 등록되면 바로 반환한다
    • 데이터베이스 읽기 요청 이벤트를 보매녀 이벤트 큐에서 대기한다
    • 자신의 차례가 되면 요청 콜백을 등록하고 바로 반환된다
  • Event Loop은 콜백의 이벤트 완료 notification을 받으면 요청을 보낸 caller에게 결과를 전달한다
  • event loop 모델은 node, netty nginx등에서 사용된다

WebFlux

  • 기존 Thread per request모델의 어노테이션에 functional routing을 사용한다 (@Controller..)
  • Reactive Stream API은 기저에 HTTP Runtime을 사용하여 상호작용할 수 있다
  • WebClient라는 reactive, non blockig한 HTTP 요청 클라이언트를 제공한다

Runtime에 Thread Model 지원

  • reactive 프로그램은 몇개의 스레드만을 최대한 사용한다
  • 우리가 선택한 실제 Reactive Stream API runtime에 따라 스래드의 수가 다르다
  • 예를들어 WEbFlux는 HttpHandler가 제공하는 Common API를 통해 다른 runtime을 사용한다
  • 이 API는 여러 서버 API와 상호작용하기 위해 추상적인 메소드를 제공한다
  • 그 중 netty가 기본으로 사용된다
  • 아래 명령어로 JVM이 생성한 스레드를 관찰할 수 있다
  • Thread.getALLStackTraces() .keySet() .stream() .collect(Collectors.toList())

Reactor Netty

  • React Netty가 기본 내장 서버로 사용된다.
  • Netty는 요청을 처리하기 위해 많은 수의 worker thread를 생성한다
  • CPU 코어 개수 이하로 생성

  • 쿼드 코어 머신일 경우
    • Netty는 스케일 가능한 event loop 모델을 제공한다
    • Event Loop Group은 하나 이상의 Event Loop를 관리한다
    • Event Loop은 반드시 계속 실행되고 있어야 한다
    • 그래서 가용 코어 개수 이상의 Event Loop를 생성하지 않는 것을 추천한다
    • Event Loop Group은 Event Loop에 새로 생성된 Channel들을 할당한다
    • 모든 operation은 같은 스레드에 의해 실행되어야 한다

출처

728x90