Webflux + R2dbc (nonblocking) vs MVC + JDBC (blocking) 성능 테스트

HYK·2022년 10월 21일
1
post-thumbnail

WebFlux vs MVC 테스트의 목적 및 개요

WebFlux 와 MVC의 성능 테스트를 눈으로 보고 스레드의 동작을 살피는 것이 테스트의 목적이다.
각각의 Controller의 요청을 받아 DB에 Sleep(IO 시간 걸리는 걸 가정) 요청을 하고 이후의 응답하는 방식으로 진행

테스트전 문제사항

처음에는 Webflux, MVC 둘 다 JDBC를 사용해서 테스트했으나 Jdbc 자체가 Blocking이라서 테스트 결과가 유의미하게 차이 나지 않았다. 어차피 요청 자체는 MVC(tomcat)도 NIO(nonblocking)로 진행되고 애플리케이션 내부의 따로 외부 api를 호출하거나 복잡한 로직이 없었기 때문에 둘의 차이가 유의미하게 나지 않았음. 따라서 Webflux는 nonblocking 방식인 R2dbc로 변경해서 진행했다.

TEST 조건 및 사용 툴

Test툴

  • yourkit(체험판)
  • jmeter

Test 조건

  • 초당 400회 총 3만개의 요청을 기준으로 부하 테스트 진행
  • HeapSize는 각 4기가로 동일하게 설정
  • 각 스레드는 12개로 설정 (Webflux 같은 경우 core(6) 수 x 2 로 만들어지기 때문에 MVC도 Webflux thread 개수에 맞춤)

결과

1. 응답 결과

  • Webflux + R2dbc

  • MVC + Jdbc

약 3만 개의 요청을 했고 Webflux의 같은 경우에는 오류율이 1퍼센트 미만이다. 약 210개의 응답을 제외하고 모든 응답을 처리했다.
반면 MVC 같은 경우는 오류율이 93퍼센트로 약 27,900개의 요청에 대한 응답을 하지 못했 으므로 대부분 응답을 하지 못하고 오류가 발생했다.
처리량에서는 약 3배의 수준을 보여주고 수신 같은 경우에도 많이 차이가 난다.

jmeter 부하테스트 중에 직접 요청하기

  • Webflux + R2dbc

  • MVC + Jdbc

다음과 같이 Webflux는 400개의 요청이 오는 와중에도 응답을 받을 수 있었다.
반면 MVC 같은 경우는 요청 시에 응답을 받을 수 없었다.

2. 스레드 상태

2-1. 스레드 흐름

  • Webflux + R2dbc

  • MVC + Jdbc

Webflux 같은 경우는 thread가 쉬지않고 계속 Runnable상태로 동작하고 있다.
반면 MVC 같은 경우에는 Jdbc 때문에 Blocking 상태가 되고 위와 같이 Waiting 상태가 된다.
여기서 Waiting이 발생하는 이유는 Jdbc를 이용할때 Connection을 얻는 과정에서 생기는 Waiting이다.

그럼 이외에 성능 차이는 없는 걸까 ??
각각의 스레드의 타임라인을 살펴보자

2-1. 스레드 전체 타임라인

  • Webflux thread timeline
    먼저 초록색으로 표시된 것은 R2dbc를 사용한 타임라인이라는 뜻이다. 초록색이 적은 이유는 Nonblock으로 작동하기 때문에 요청을 보내고 다른 타임라인은 다른 일을 처리했기 때문이다.
    회색으로 표시된 범위에서 R2dbc를 사용한 시간을 보면 78ms 정도의 시간이 걸렸다는 것을 알 수 있다.
  • MVC thead timeline

MVC 타임라인의 분홍색 부분은 sql에 관련된 타임라인을 말한다. 즉 여기서는 sql(요청, 응답)을 시작하고 끝나는 시간이라고 생각하면 된다.

MVC 같은 경우는 거의 모든 타임라인에 Jdbc가 물려있었고 대부분의 할당 시간을 Jdbc의 응답을 기다리는 대에 소비 중이다.

분홍색 부분을 참고해서 보면 쿼리를 DB에 날린 후에 스레드는 Runnable 상태지만 Jdbc의 응답을 기다리고 있으므로 실질적으로 다른 일을 처리하지 않고 있는 것을 확인할 수 있다. 즉 Blocking 상태이다.

2-2. 스레드 상세 타임라인

  • Webflux thread timeline
    nio-9 스레드의 상태 변화이다.
    첫 번째 사진의 동그라미 친 타임라인에 thread가 실행한 작업을 보면 R2dbc의 sql 문을 실행한 것을 할 수 있다.
    두 번째 사진의 동그라미 친 부분은 첫 번째 사진의 바로 다음 타임라인이다. 보면 R2dbc로 DB에 요청을 한 후에 바로 제어권을 넘겨받아 다른 작업을 실행하고 있는 것을 볼 수 있다. 바로 Nonblocking 방식으로 동작하는 것을 살펴볼 수 있다

  • Webflux thread timeline
    exec-9 스레드의 상태 변화이다.
    첫 번째 사진도 Webflux와 마찬가지로 동그라미 친 타임라인의 thread가 실행한 작업이다. Jdbctemplate의 query를 실행하고 있다.
    두 번째 사진도 마찬가지로 Jdbctemplate의 query를 실행하고 있다. 그런데 MVC 같은 경우는 타임라인에 색칠된 부분은 다 Jdbc 관련해서 실행 중이다.(Webflux는 대부분 흰색 -> sql 관련 작업 X)

정리

이 테스트의 자료를 해석한 결과는 이렇다.
이 애플리케이션은 DB에 sleep을 날리는 로직 외에는 다른 로직이 없다.
MVC 같은 경우에는 대부분 Jdbc에 쿼리를 날리고 거기에 대한 응답을 대기하는 시간이 길기 때문에(Block) 스레드들이 상태는 Runnable이지만 DB의 응답을 기다리느라 다른 로직을 처리할 수 없다(ex request 받기)
따라서 Webflux처럼 비동기적으로 DB에 요청을 하고 다른 로직을 실행할 수 있는 Webflux가 상대적으로 훨씬 많은 요청을 받을 수 있는 것이다.

profile
Test로 학습 하기

0개의 댓글