안녕하세요, 이번엔 이벤트드리븐 서비스의 개선작업을 하다가 알게된 cloudwatch 통계지표 조회방법을 공유드립니다.
이 작업을 하게된 이유를 말씀드리자면 이렇습니다.
현재 SQS 를 이용한 이벤트드리븐 환경에서 동작하는 서비스가 있습니다.
이런 저런 정보들을 동기화하기 위한 목적으로 사용하고 있고, 이 서비스는 멀티쓰레드 환경에서 동작하도록 되어있습니다.
혹시라도 이벤트가 지연될 경우를 대비해서 쓰레드 개수를 수시로 수동조절할 수 있도록 구성해두었죠.
그리고 지연이 발생하여 SQS 메시지가 발행된 뒤 일정 시간동안 처리를 못하여 큐에 계속 남아있게되면 alert가 발생하도록 되어있습니다.
즉, SQS의 ApproximateAgeOfOldestMessage 지표값을보고 너무 오래동안 처리가 안될 경우 alert를 받고 수동으로 쓰레드 개수를 조절하는 형태로 위기를 벗어나고 있습니다. 그런데 이 드물디 드문 사건이라도 개발자라면, 그리고 가능한 케이스라면 그냥 전부 다 자동화를 해놓아야 하지 않을까 생각이 들어 개선 작업에 들어갔습니다.
일단 SQS에서 제공하는 모니터링 지표는 아래와 같습니다. (AWS 콘솔화면의 모니터링 탭에서 볼 수 있는 것들입니다)
이 지표에 해당하는 통계수치는 cloudwatch 에서 수집이 됩니다.
클라우드워치에서 수집된 데이터를 가지고 모니터링탭에 그래프로 보여주는 것이죠.
이제 제가 원하는 Approximate Age Of Oldest Message 에 대한 데이터를 뽑아보도록 하겠습니다.
일단 앱의 구성은 다음과 같습니다.
AWS java sdk 에서는 cloudwatch 서비스에서 제공하는 API를 호출하여 클라우드워치 데이터를 조회할 수 있도록 cloudwatch client를 제공합니다. 제일 먼저 이 클라이언트를 빈으로 등록합니다.
@Configuration
public class AWSConfig {
private AWSCredentialsProvider awsCredentialsProvider() {
List<AWSCredentialsProvider> credentialsProviders = new ArrayList<>();
credentialsProviders.add(new InstanceProfileCredentialsProvider(true));
credentialsProviders.add(new ProfileCredentialsProvider());
return new AWSCredentialsProviderChain(credentialsProviders);
}
@Bean
public AmazonCloudWatch cloudWatchClient() {
return AmazonCloudWatchClientBuilder.standard()
.withCredentials(awsCredentialsProvider())
.withRegion(Regions.fromName("ap-northeast-2"))
.build()
;
}
}
그리고 서비스 레이어에서 이 cloudWatchClient를 가져다 써보겠습니다.
private void getQueueStatus(String queueName) {
long currentMillis = System.currentTimeMillis();
long fiveMinutesInMillis = 5 * 60 * 1000;
GetMetricStatisticsRequest statisticsRequest = new GetMetricStatisticsRequest()
.withNamespace("AWS/SQS").withMetricName("ApproximateAgeOfOldestMessage")
.withStatistics(Statistic.Maximum).withPeriod(300)
.withStartTime(new Date(currentMillis - fiveMinutesInMillis))
.withEndTime(new Date(currentMillis))
.withDimensions(new Dimension().withName("QueueName").withValue(queueName));
GetMetricStatisticsResult result = cloudWatch.getMetricStatistics(statisticsRequest);
log.debug("dataPoints: {}", result.getDatapoints());
}
cloudWatchClient 를 이용하여 통계수치 데이터를 조회하려면 GetMetricStatisticsRequest 객체를 만들어서 넣어주어야 합니다.
이 객체에 설정해줘야 하는 값들 중 필수적인 것들만 설정해보았습니다.
간략히 설명하자면 다음과 같습니다.
(참고: Available CloudWatch metrics for Amazon SQS)
설정값은 현재 지난 5분동안(from endTime to startTime) 5분간격(period)의 데이터를 조회하도록 되어있으므로 1개의 data point 가 조회가 됩니다. 그리고 unit은 초단위로 나옵니다.
위 코드를 실행해서 조회한 sqs의 Approximate Age Of Oldest Message 지표값은 다음과 같이 출력됩니다.
dataPoints: [{Timestamp: Thu Dec 29 16:08:00 KST 2022,Maximum: 249.0,Unit: Seconds,}]
설정값을 변경하여 period를 60으로 넣어서 실행하면 5개가 조회됩니다.
dataPoints: [{Timestamp: Thu Dec 29 17:03:00 KST 2022,Maximum: 3254.0,Unit: Seconds,}, {Timestamp: Thu Dec 29 17:07:00 KST 2022,Maximum: 3554.0,Unit: Seconds,}, {Timestamp: Thu Dec 29 17:05:00 KST 2022,Maximum: 3433.0,Unit: Seconds,}, {Timestamp: Thu Dec 29 17:06:00 KST 2022,Maximum: 3491.0,Unit: Seconds,}, {Timestamp: Thu Dec 29 17:04:00 KST 2022,Maximum: 3370.0,Unit: Seconds,}]
조회된 5개의 데이터는 지난 5분 구간(startTime, endTime)에서 1분 간격(period) 데이터를 조회했을 때의 결과입니다. 그리고 이 값은 Approximate Age Of Oldest Message, 즉, 대략적으로 얼마나 오래되었는가를 나타내는 값이므로 1분 간격 데이터를 조회한다면 약 1분(60초)의 시간차이가 있겠죠. 출력된 데이터의 순서가 시간순이 아니니 시간순으로 정렬해보면 약 1분 정도 차이가 난다는 것을 확인할 수 있습니다.
[
{Timestamp: Thu Dec 29 17:03:00 KST 2022,Maximum: 3254.0,Unit: Seconds,},
{Timestamp: Thu Dec 29 17:04:00 KST 2022,Maximum: 3370.0,Unit: Seconds,}
{Timestamp: Thu Dec 29 17:05:00 KST 2022,Maximum: 3433.0,Unit: Seconds,},
{Timestamp: Thu Dec 29 17:06:00 KST 2022,Maximum: 3491.0,Unit: Seconds,},
{Timestamp: Thu Dec 29 17:07:00 KST 2022,Maximum: 3554.0,Unit: Seconds,},
]
17:03 에서 17:04는 예외적으로 약 2분 차이가 나네요 ^^;;
이상으로 AWS cloudwatch API로 SQS의 metric을 조회하는 방법에 대해 알아보았습니다.
저는 이렇게 조회한 데이터를 가지고 일정 시간을 넘어설 경우 쓰레드 개수를 scale in/out 하도록 서비스를 구현했습니다.
도움이 되셨다면 공감꾹 부탁드려요~
[IntelliJ] 신규 생성 프로젝트의 빌드 오류 (Could not resolve org.springframework.boot:spring-boot-gradle-plugin:3.2.1) (1) | 2024.01.03 |
---|---|
SpringBoot 2.3 -> 2.5 업그레이드 후기 (0) | 2023.12.29 |
MariaDB로 AWS Aurora 연동시 readOnly 트랜잭션이 writer 쪽에서 실행되는 현상 분석 (0) | 2022.12.26 |
[AWS] redis-cli 를 이용한 elasticache 데이터 조회 (0) | 2022.05.27 |
[AWS] EC2 에서 Elasticache(Redis 클러스터) 접속하기 (0) | 2022.05.26 |