🍃 Spring

[Spring] 스프링에서 가상 스레드를 이용한 부하테스트

loose 2024. 3. 15. 17:47
반응형
a thousand hearings aren’t worth one seeing, and a thousand seeings aren’t worth one doing

Spring Property 설정

spring.threads.virtual.enabled=true
server.tomcat.threads.max=1
server.tomcat.threads.min-spare=1

Spring에서 JDK 21을 이용할 때 가상 스레드를 활용하기 위해서는 spring.threads.virtual.enabled=true를 활성화해줍니다.

부하테스트를 위해 Thread는 1개로 유지합니다.

코드 작성

@GetMapping("/test")
public String test() throws InterruptedException {
  Thread.sleep(50);
  return "test";
}

간단히 위와 같은 Controller Method 하나를 작성해보고 Gatling에 Scala 코드로 동시 1000번 요청을 진행하는 방식으로 작성한 뒤 부하 테스트를 진행합니다.

package test
import scala.concurrent.duration._
import io.gatling.core.Predef._
import io.gatling.http.Predef._
import io.gatling.jdbc.Predef._

class RecordedSimulation extends Simulation {

	val httpProtocol = http("testSimaulation")
		.get("http://127.0.0.1:8080/test")
    	.header("Client-Version", "1")
    
	val scn = scenario("Scenario1")
		.exec(httpProtocol)
    
    setUp( 
        scn.inject(atOnceUsers(1000)) 
    )
}

부하 테스트

 

기존 Tomcat Thread를 활용한 방식

 

Virtual Thread를 활용한 방식

 

기존 MVC 작업은 Tomcat Thread 1개가 Sleep에 들어감에 따라 Sleep이 끝나야만 그 다음 작업이 처리 되므로 1000번째 요청인 하위 99퍼센트 요청은 55초째에 마무리된 것을 확인할 수 있습니다. 

(Thread Sleep을 50ms로 줬으니 50ms * 1000 = 50000ms) 

하지만 Virtual Thread를 사용한 방식은 하위 99퍼센트의 요청도 0.4초안에 끝나는 것을 확인할 수 있습니다. 

왜 이런걸까? 

가상 스레드 개념은 JVM에서 사용하는 Thread에 여러개의 가상 스레드를 붙인 뒤 kernel에 넘겨서 사용하는 개념입니다. 

그러므로 가상 스레드는 OS Thread 내에서 실행됩니다. 

하지만 가상 스레드에서 실행되는 코드가 블로킹 I/O 작업을 호출하면 자바 런타임은 다시 시작될 수 있을 때까지 가상 스레드를 일시 중지합니다. 

그럼 OS Thread와 연결 됐었던 가상 스레드는 중지 상태에 돌아가지만 OS Thread는 다른 작업을 처리할 수 있는 구조라서 위와 같은 결과를 볼 수 있다고 보면 됩니다.

 

 

 

 

728x90