ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Spring WebFlux] 기존 웹 서버와의 차이점과 꼭 주의해야할 점 (Netty)
    Spring/WebFlux 2024. 11. 18. 20:03

    1. Netty와 Tomcat의 차이

    Spring WebFlux는 논블로킹 리액티브 프로그래밍 모델을 지원하며 기본적으로 Netty를 웹 서버로 사용한다.

    이는 블로킹 기반 웹 서버인 Tomcat과는 스레드 관리 방식 등 다소 차이가 있기에 그 차이를 이해해야만 효율적인 reactive 프로그래밍이 가능하다.

    (Tomcat과 같은 서블릿 컨테이너를 활용해서도 Flux와 Mono data stream을 반환할 수 있기는 하다.)

     

     

    2. 이벤트 루프를 사용하는 Netty의 특성

    Netty는 이벤트 루프 기반의 네트워크 애플리케이션 프레임워크로, 논블로킹 I/O 작업을 효율적으로 처리하기 위해 설계되었다.

    Tomcat은 스레드 풀을 두고 다수의 스레드를 만들어두고 개별 요청마다 스레드를 할당한다.

    반면에 Netty는 쓰레드를 기본적으로 CPU 코어 수 × 2 만큼 생성되고 이를 여러 요청에서 재사용한다.

     

    이벤트 루프 기반 아키텍처의 주요 특성은 다음과 같다.

    • 소수의 스레드(이벤트 루프 스레드)가 모든 연결과 요청을 처리한다.
    • 이벤트 루프 스레드에서 요청을 이벤트 큐로 관리하며 여러 이벤트를 처리하기 때문에 스레드 간 컨텍스트 전환이 적다.
    • 요청 대기 상태에서 낭비되는 쓰레드가 없고 적은 수의 스레드로도 아주 많은 수의 요청을 처리할 수 있다.

     

    3. 이벤트 루프를 이해하는것의 중요성

    이벤트 루프 모델은 높은 동시성을 제공하지만 앞서 언급했듯이 쓰레드 수가 제한적이기 때문에

    이벤트 루프 스레드에서 I/O라던지 Blocking 작업이 발생하면 전체 성능에 심각한 영향을 미친다.

     

    예를 들어 아래와 같이 5초가 걸리는 유저 검색 작업이 있다고 가정해보자.

    @GetMapping("/findUser")
    public Mono<String> findUserExample() {
        return Mono.fromCallable(() -> {
            Thread.sleep(5000); // 5초 대기
            return "User found";
        });
    }

     

    위처럼 요청이 들어온 스레드에서 그대로 작업을 한다면 이벤트 루프 스레드에서 작업이 이루어지게 된다.

    이벤트 루프 스레드에서 I/O 작업이 이루어지기 때문에 5초간 이벤트 루프 스레드가 점유당하게 된다.

    만약에 Netty서버에 이벤트 루프 쓰레드가 4개만 생성되어 있다면,

    4명의 유저가 동시 접속하면 나머지 유저들은 5초간 아무런 응답도 받을 수 없게 된다.

    이는 5초에 4명의 유저만 처리할 수 있는 아주 비효율적인 웹 서비스가 될 것이다.

     

    어떻게 방지할 수 있을까?

     

    I/O 작업을 별도의 쓰래드로 분리해야한다.

    publishOn, subScribeOn 등을 사용하여 Scheduler을 설정하면 쓰레드를 이벤트 루프 쓰레드로부터 분리할 수 있다.

     

    다음과 같이 코드를 수정할 수 있다.

    @GetMapping("/findUser")
    public Mono<String> findUserExample() {
        return Mono.fromCallable(() -> {
            Thread.sleep(5000);
            return "User found";
        }).subscribeOn(Schedulers.boundedElastic()); // 블로킹 작업을 별도 스레드 풀에서 실행
    }

     

    이렇게 하면 이벤트 루프 쓰레드는 바로 유저에게 응답을 보내고 다른 응답을 처리할 수 있게 된다.

     

    기억해야 할 것은 이벤트 루프 쓰레드에서는 절대 Blocking을 유발할 수 있는 요소가 실행되어서는 안 된다는 것이다.

    Blocking을 유발하는 작업에 Scheduler을 설정해서 쓰래드를 할당해서 해결할 수 있다.

    댓글

Designed by Tistory.