WebFlux 와 MVC의 성능 테스트를 눈으로 보고 스레드의 동작을 살피는 것이 테스트의 목적이다.
각각의 Controller의 요청을 받아 DB에 Sleep(IO 시간 걸리는 걸 가정) 요청을 하고 이후의 응답하는 방식으로 진행
처음에는 Webflux, MVC 둘 다 JDBC를 사용해서 테스트했으나 Jdbc 자체가 Blocking이라서 테스트 결과가 유의미하게 차이 나지 않았다. 어차피 요청 자체는 MVC(tomcat)도 NIO(nonblocking)로 진행되고 애플리케이션 내부의 따로 외부 api를 호출하거나 복잡한 로직이 없었기 때문에 둘의 차이가 유의미하게 나지 않았음. 따라서 Webflux는 nonblocking 방식인 R2dbc로 변경해서 진행했다.
Webflux + R2dbc
MVC + Jdbc
약 3만 개의 요청을 했고 Webflux의 같은 경우에는 오류율이 1퍼센트 미만이다. 약 210개의 응답을 제외하고 모든 응답을 처리했다.
반면 MVC 같은 경우는 오류율이 93퍼센트로 약 27,900개의 요청에 대한 응답을 하지 못했 으므로 대부분 응답을 하지 못하고 오류가 발생했다.
처리량에서는 약 3배의 수준을 보여주고 수신 같은 경우에도 많이 차이가 난다.
다음과 같이 Webflux는 400개의 요청이 오는 와중에도 응답을 받을 수 있었다.
반면 MVC 같은 경우는 요청 시에 응답을 받을 수 없었다.
Webflux 같은 경우는 thread가 쉬지않고 계속 Runnable상태로 동작하고 있다.
반면 MVC 같은 경우에는 Jdbc 때문에 Blocking 상태가 되고 위와 같이 Waiting 상태가 된다.
여기서 Waiting이 발생하는 이유는 Jdbc를 이용할때 Connection을 얻는 과정에서 생기는 Waiting이다.
그럼 이외에 성능 차이는 없는 걸까 ??
각각의 스레드의 타임라인을 살펴보자
MVC 타임라인의 분홍색 부분은 sql에 관련된 타임라인을 말한다. 즉 여기서는 sql(요청, 응답)을 시작하고 끝나는 시간이라고 생각하면 된다.
MVC 같은 경우는 거의 모든 타임라인에 Jdbc가 물려있었고 대부분의 할당 시간을 Jdbc의 응답을 기다리는 대에 소비 중이다.
분홍색 부분을 참고해서 보면 쿼리를 DB에 날린 후에 스레드는 Runnable 상태지만 Jdbc의 응답을 기다리고 있으므로 실질적으로 다른 일을 처리하지 않고 있는 것을 확인할 수 있다. 즉 Blocking 상태이다.
이 테스트의 자료를 해석한 결과는 이렇다.
이 애플리케이션은 DB에 sleep을 날리는 로직 외에는 다른 로직이 없다.
MVC 같은 경우에는 대부분 Jdbc에 쿼리를 날리고 거기에 대한 응답을 대기하는 시간이 길기 때문에(Block) 스레드들이 상태는 Runnable이지만 DB의 응답을 기다리느라 다른 로직을 처리할 수 없다(ex request 받기)
따라서 Webflux처럼 비동기적으로 DB에 요청을 하고 다른 로직을 실행할 수 있는 Webflux가 상대적으로 훨씬 많은 요청을 받을 수 있는 것이다.