Notepad

WebFlux를 선택한 이유

고성능 API를 위해 WebFlux를 선택한 이유

Spring MVC

  • Thread Per Request Model
  • Thread 개수 == 200(SpringBoot AutoConfig default value)
  • Thread에서 REST API 호출 시 응답을 받기까지 Waiting 상태가 되며 blocking
  • 200개의 Thread가 얼마 되지 않는 CPU Core를 점유하기 위해서 Thread 경합하는 현상 발생
    • 대부분의 API 개발자가 사용하는 Machine Core 개수는 2,4,8 정도

Spring WebFlux

  • EventLoop Model
    • 사용자들의 요청이나 애플리케이션 내부에서 처리해야하는 작업들은 모두 Event라는 단위로 관리
    • Event Queue에 적재되어 순서대로 처리되는 구조
    • EventLoop
      • Event로 처리하는 Thread Pool
      • Event Queue에서 Event를 뽑아서 하나씩 처리
  • 리액터 라이브러리와 Netty를 기반으로 동작
    • Netty는 Tomcat과 달리 Thread Pool의 Thread 개수가 Machine Core 개수의 두배
  • Spring MVC처럼 Thread가 Block 되어 I/O가 끝날 때까지 Waiting 하는 대신 I/O가 시작되기 전 작업도 Event I/O가 종료되면 처리할 작업도 Event로 만들어져 Queue에 들어감
  • NIO를 이용하여 I/O 작업 처리를 하기 때문에 Thread 상태가 Block 되지 않음
  • Thread Per Request Model 방식 보다 Context Switch 오버헤드가 줄고 Thread 숫자도 작기 때문에 Core를 차지하기 위한 경합도 줄어듬
  • 높은 처리량이 가능한 이유
    • EventLoop 사용과 Non-blocking I/O 사용
  • Non-blocking I/O 대신 Blocking I/O 를 사용한다면?
    • 전반적인 성능 하락 발생
    • 상대적으로 적은 Thread Pool을 유지하기에 EventLoop가 Event Queue에 있는 Event를 빨리 처리 할 수 없음
    • Runnable 상태의 Thread들이 CPU 점유

나의 WebFlux가 느린 이유

테스트 시나리오 아키텍처

  • 중간에 있는 API 서버가 성능 부하 클라이언트의 부하를 받고 Redis에서 데이터를 가지고 와서 응답하는 시나리오

비교대상

  • Spring MVC 애플리케이션
  • Spring WebFlux 애플리케이션

성능 측정 결과

  • Spring MVC: 3,775 tps
  • Spring WebFlux
    • 1차: 706 tps
    • 2차: 693 tps
    • 3차: 4,453 tps
    • 4차: 5,977 tps

성능 개선 사항

  • 2차: LogBack의 AsyncAppender 적용
  • 3차: log() 제거 및 RollingFileAppender로 변경
  • 4차: map(), flatMap() 수정

문제 및 개선

  • 1차: log() 메서드
  • 2차: AsyncAppender 사용
  • 3차: log() 메서드 제거
  • 4차: flatMap, map 리팩토링

다른 성능 개선 사항

  • BlockHound
  • Lettuce 설정
  • Avoiding Reactor Meltdown(from InfoQ)

컨퍼런스 영상

'dev > 기타' 카테고리의 다른 글

Angular Git Commit Message Convention  (0) 2022.06.13
REST 리소스 명명 가이드  (0) 2022.06.06
M1 Macbook 윈도우 설치(UTM)  (0) 2022.04.11
JUnit 5  (0) 2020.11.22
[디자인 패턴] 스트래티지 패턴  (0) 2020.04.30
profile

Notepad

@Apio

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!