모니터링

내가 만든 ThreadPool 모니터링 하기

Junuuu 2023. 11. 17. 00:01

개요

  • 내가 만든 ThreadPool 모니터링하기

 

의존성 및 yml 설정

dependencies {
	implementation("org.springframework.boot:spring-boot-starter-actuator")
	implementation("io.micrometer:micrometer-core")
}

actuator를 통한 모니터링과 custom metric을 등록하기 위해 micrometer 의존성을 추가합니다.

 

application.yml

management:
  health:
    db:
      enabled: false
    redis:
      enabled: false
  endpoints:
    web:
      exposure:
        include: metrics,health

 

Spring Boot Actuator Metrics

spring boot application 기동 후 다음과 같은 메트릭정보를 확인할 수 있습니다.

메모리 사용량, GC 통계, 데이터베이스 연결 통계등 다양한 정보를 볼 수 있습니다.

 

 

ThreadPoolConfig

@Configuration
class ThreadPoolConfig{

    @Bean
    fun myExecutor(): ThreadPoolTaskExecutor{
        val executor = ThreadPoolTaskExecutor()
        executor.corePoolSize = 1000
        executor.maxPoolSize = 1000
        executor.queueCapacity = 0
        executor.setThreadNamePrefix("test-task-")
        executor.setWaitForTasksToCompleteOnShutdown(true)
        executor.setAwaitTerminationSeconds(25) // 기본 0초로 설정되어 있음. task 내려갈 때까지 25초 기다리고 앱 종료하도록 설정
        executor.initialize()
        return executor
    }
}

1000개의 thread pool을 만들었습니다.

 

Controller

@RestController
class MonitoringTestController(
    private val addThreadTestService: AddThreadTestService,
) {

    @GetMapping("/add-thread")
    fun test(): String{
        repeat(100){
            addThreadTestService.addAsyncThread()
        }
        return "add 30 thread with 1000s sleep"
    }
}

 

Service

@Service
class AddThreadTestService {

    @Async(value = "myExecutor")
    fun addAsyncThread(){
        //1000초 Sleep해라
        Thread.sleep(1000 * 1000)
    }
}

비동기로 myExecutor 스레드풀을 이용하게 만들어 컨트롤러에서 100번의 호출로 여러 개의 스레드를 사용하게 만들었습니다.

 

 

메트릭 등록

@Configuration
class MonitoringConfig {
    @Bean
    fun metricsCommonTags(@Qualifier("myExecutor") myExecutor: ThreadPoolTaskExecutor): MeterRegistryCustomizer<MeterRegistry> {
        return MeterRegistryCustomizer { registry: MeterRegistry? ->
            Gauge.builder(
                "custom.executor.active.threads",
                myExecutor
            ) { obj: ThreadPoolTaskExecutor ->
                obj.activeCount
                    .toDouble()
            }
                .tags("name", "customTaskExecutor")
                .register(registry!!)
        }
    }
}

custom.executor.active.threads 라는 메트릭을 등록할 수 있습니다.

Guage 형태로 메트릭을 등록하여 변동이 있을 수 있는 값을 상태나 크기를 실시간으로 활용하는 데 사용됩니다.

 

 

테스트 후 메트릭 관찰

Controller의 Endpoint를 3번 호출 후 만들어둔 메트릭경로로 이동하면 300개의 스레드가 사용 중인 것을 알 수 있습니다.