모종닷컴

Intellij Idea &Visual VM (with WebFlux, Vegeta) 본문

Programming/Intellij IDEA

Intellij Idea &Visual VM (with WebFlux, Vegeta)

모종 2023. 2. 18. 21:21
반응형

요즘 제 관심사는 Reactive Programming인데요. 문득 궁금한 부분이 생겼습니다. Reacitve 시스템은 기존 전통적인 방식과 비교하여 어떤 점이 좋아진 걸까요? 이를 위해 Spring MVC와 Spring WebFlux를 이용해서 각각 데모 애플리케이션을 만들었습니다. 

그리고 이 애플리케이션의 성능을 측정하기 위해 APM이 필요했는데요. 인텔리제이와 Visual VM을 연동하는 방법이 있다는 것을 발견하여 공유드리고자 포스팅을 작성해 보도록 하겠습니다.

Visual VM 설치

https://visualvm.github.io/download.html

위 페이지를 통해 먼저 Visual VM을 설치해주세요. 그리고 압축을 풀어주세요.

 

VisualVM: Download

Download VisualVM is distributed as a standalone tool at GitHub, and as an optional component of the GraalVM. Both are the same bits with the same features. Standalone tool runs on any compatible JDK, component is configured to run using the host GraalVM.

visualvm.github.io

 

Intellij IDEA 플러그인 설치 및 설정

Intellij IDEA의 환경설정으로 들어가줍니다. 맥 기준 단축키는 Command + , 입니다.

Plugins 탭에서 Visual VM 검색을 하고 아래 플러그인을 설치해 줍니다.

플러그인이 설치되었다면 IDE를 재시작해서 다시 환경설정을 들어가 주세요. 그러면 좌측 탭에서 VisualVM Launcher라는 탭이 새로 생겼을 텐데요. 안 보인다면 좌측에서 VisualVM을 검색해서 찾아주세요. 그런 다음 아래와 같이 VisualVM executable에 위에서 설치한 VisualVM의 실행파일을 넣어주면 됩니다. 아마 bin 폴더 밑에 visualvm 파일이 있을 겁니다.

설정을 적용하고 나면 애플리케이션을 실행하는 부분에 아래 사진의 빨간색 박스에 해당하는 버튼이 생성되어 있을 겁니다. 

 

테스트를 위한 애플리케이션 생성

테스트를 위해 간단한 Demo 애플리케이션을 만들어보겠습니다.

gradle.build.kts

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    id("org.springframework.boot") version "2.7.8"
    id("io.spring.dependency-management") version "1.0.15.RELEASE"
    kotlin("jvm") version "1.6.21"
    kotlin("plugin.spring") version "1.6.21"
}

group = "com.example"
version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_11

repositories {
    mavenCentral()
}

dependencies {
    implementation("org.springframework.boot:spring-boot-starter-webflux")
    implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
    implementation("io.projectreactor.kotlin:reactor-kotlin-extensions")
    implementation("org.jetbrains.kotlin:kotlin-reflect")
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor")
    testImplementation("org.springframework.boot:spring-boot-starter-test")
    testImplementation("io.projectreactor:reactor-test")
}

tasks.withType<KotlinCompile> {
    kotlinOptions {
        freeCompilerArgs = listOf("-Xjsr305=strict")
        jvmTarget = "11"
    }
}

tasks.withType<Test> {
    useJUnitPlatform()
}

WebFluxApplication.kt

@SpringBootApplication
class WebfluxApplication 

fun main(args: Array<String>) {
    runApplication<WebfluxApplication>(*args)
}

DemoRouterConfig.kt

@Configuration
class DemoRouterConfig(
    private val demoService: DemoService
) {
    @Bean
    fun demoRouter(): RouterFunction<ServerResponse> {
        return RouterFunctions.route()
            .GET("demo", demoService::hello)
            .build()
    }
}

DemoService.kt

interface DemoService {
    fun hello(serverRequest: ServerRequest): Mono<ServerResponse>
}

@Service
internal class DemoServiceImpl : DemoService {
    override fun hello(serverRequest: ServerRequest) = ServerResponse.ok().body(
        Mono.just("webflux")
            .delayElement(Duration.ofMillis(500))
            .map {
                for (i in 1..100_000_000) {
                }
                it
            },
        String::class.java
    )
}

application.properties

server.port=9091

부하툴 설치

부하를 좀 주기 위해 툴을 설치할 것입니다. 툴은 vegeta를 사용하도록 하겠습니다. Apache Benchmark 가 기본적으로 맥에 깔려있기는 하지만 뭔가 버그인지 첫 번째 요청에서 blocking이 되는 이슈가 있어서 가볍게 사용할 수 있는 vegeta를 깔았습니다.

(이름이 상당히 익숙할 텐데 그 베지터가 맞습니다 ㅋㅋ)

install

터미널에서 아래 명령어를 통해 vegeta를 설치합니다. 설치가 잘 되었다면 vegeta --version에서 출력이 잘 될 것인데, 만약 설치가 잘되지 않았다면 위 vegeta 링크를 통해 한번 확인을 해보세요.

brew update && brew install vegeta

 

테스트

이제 애플리케이션을 실행해 보도록 하겠습니다.

둘 중 원하는 것으로 실행시키면 되는데 Debug는 필요 없으므로 저는 좌측 Run 모드로 실행시켰습니다. 실행을 시키면 VisualVM이 자동적으로 실행이 될 겁니다.

좌측 탭에서 실행시킨 애플리케이션을 선택하고 우측에서 Monitor를 선택해 주세요.

이제 부하를 걸어보도록 하겠습니다. 터미널에 들어가서 아래 명령어를 입력해서 vegeta가 애플리케이션에 부하를 걸도록 합니다.

echo "GET http://localhost:9091/demo" | vegeta attack -duration 1s -rate=100 | tee result | vegeta report

위는 1초에 100개의 요청을 해당 엔드포인트에 요청하는 것인데 원하시는 입맛대로 설정해서 던져주시면 됩니다. 예로 초당 200건씩 10초 동안 부하를 주고 싶다면 아래처럼 수정해서 던져주시면 됩니다.

vegeta attack -duration 10s -rate 200 

(명령어가 굉장히 재밌는데 베지터가 애플리케이션에 어택을 겁니다 ㅋㅋㅋ)

저는 100건만 동시요청 해보도록 하겠습니다. 100건을 실행하는데 총 1.7초가 걸렸네요.

(왜 이렇게 오래 걸렸나하고 생각해봤는데 다른 부분까지 테스트한다고 Filter에다가 제가 Duration을 걸어놨었군요. 다른 분들은 훨씬 빠르게 응답을 받았을 거에요)

이제 VisualVM을 보면 전 아래와 같은 결과를 받았네요. 순간적으로 CPU가 20퍼센트까지 쳤고, 메모리 힙 사이즈가 117MB까지 찼었네요. WebFlux를 이용했더니 스레드가 정말 작게 생성이 되었어요.. 아마 이 스레드 개수도 머신마다 차이가 있을 겁니다. 해당 스레드 개수는 머신의 CPU 개수와 상관이 있을 텐데요. 저는 10 core라서 이렇게 생성이 된 것 같습니다. 다른 분들은 좀 더 많거나, 좀 더 적을 수 있습니다.

 

반응형

'Programming > Intellij IDEA' 카테고리의 다른 글

Intellij IDEA Gradle JVM 설정  (0) 2023.02.25
IntelliJ IDEA 디버깅 팁  (0) 2022.11.12