Spring

Spring boot 3.x + Amazon SQS 적용기

beekei 2023. 5. 30. 16:21
반응형

개요

업무상 Amazon SQS를 적용할 일이 있어 예전에 정리한 SQS 설정 방법대로 설정했지만 Listener이 작동하지 않는 이슈가 있었습니다.

서칭해본 결과 Spring Cloud AWS 2.x 버전은 Spring Boot 3.x에 완전히 호환되지 않는 것처럼 보입니다.

 

AWS @SqsListener not working with spring cloud (using springboot 3)

Currently, we have an SQS client configured using an IAM Role that is picked up on the cluster. However, migrating over to Springboot 3 the @SqsListener is no longer consuming the messages. NOTE: S...

stackoverflow.com

 

Spring Boot 3.x에 호환될 버전을 찾아보니 2023년 05월 02일에 Spring Cloud AWS 3.x가 발표되었습니다.

 

Announcing Spring Cloud AWS 3.0.0

This is a guest post from the maintainers of Spring Cloud AWS. Spring Cloud AWS 3.0.0 Spring Cloud AWS 3.0 is a recent release of the Spring Cloud AWS project. This version represents a complete rewrite of the library using AWS SDK v2 for Java. Since this

spring.io

자세히 확인해보면 Spring Boot 3.0과 호환이 가능하고, SQS 모듈이 재작성되었다고 합니다.


2.x버전과 설정법도 조금 달라진 듯 하여 따로 정리하였습니다.

Spring Boot 3.0.5 기준입니다.

1. dependency 추가

build.gradle 

dependencies {
    ...
    implementation platform("io.awspring.cloud:spring-cloud-aws-dependencies:3.0.1")
    implementation 'io.awspring.cloud:spring-cloud-aws-starter-sqs'
}

2. Amazon SQS 설정

리전과 자격증명, Sender, Listerner에 대한 설정을 등록합니다.

AmazonSQSConfig.java

@Configuration
public class AmazonSQSConfig {

    @Value("${spring.cloud.aws.region.static}")
    private String region;

    @Value("${spring.cloud.aws.credentials.access-key}")
    private String accessKey;

    @Value("${spring.cloud.aws.credentials.secret-key}")
    private String secretKey;
	
    // 클라이언트 설정
    @Bean
    public SqsAsyncClient sqsAsyncClient() {
        return SqsAsyncClient.builder()
            .credentialsProvider(() -> new AwsCredentials() {
                @Override
                public String accessKeyId() {
                    return accessKey;
                }
                @Override
                public String secretAccessKey() {
                    return secretKey;
                }
            })
            .region(Region.of(region))
            .build();
    }
    
    // Listener Factory 설정 (Listener쪽에서만 설정하면 됨)
    @Bean
    public SqsMessageListenerContainerFactory<Object> defaultSqsListenerContainerFactory() {
        return SqsMessageListenerContainerFactory
            .builder()
            .sqsAsyncClient(sqsAsyncClient())
            .build();
    }
	
    // 메세지 발송을 위한 SQS 템플릿 설정 (Sender쪽에서만 설정하면 됨)
    @Bean
    public SqsTemplate sqsTemplate() {
        return SqsTemplate.newTemplate(sqsAsyncClient());
    }

}

credentialsProvider를 따로 코드로 작성하지 않아도 환경변수, 프로필 파일로도 자격증명이 가능합니다.

위 방법이 불가할 경우는 아래와 같이 property를 지정해서 증명이 가능합니다.

참고로 Spring Cloud AWS 3.x에서 property는 아래와 같이 변경되었으니 참고 바랍니다.

나의 경우는 AWS ECS Fargate를 이용하므로 서버에 접속할 수 없어 프로필 파일로는 자격증명이 불가했고 환변경수를 더 늘리고 싶지 않아서 위처럼 property에 설정해보았지만 무슨 이유인지 자동적으로 자격증명이 되지 않았습니다..

그래서 클라이언트 설정쪽에서 credentialsProvider를 따로 코드로 설정해주었습니다.

다른 설정은 AWS 콘솔 상에서 컨트롤 하기 위해 따로 코드에서 지정하지 않았습니다.


3. Message Sender

메세지를 보내는 클래스를 작성합니다.

Queue가 FIFO인 경우 순서가 보장되고 Group ID로 중복데이터를 제거할 수 있습니다.

@Component
@RequiredArgsConstructor
public class AmazonSQSSender {
	
    private final SqsTemplate template;

    @Value("${application.amazon.sqs.queue-name}")
    private String queueName;

    public AmazonSQSSender(SqsAsyncClient sqsAsyncClient) {
        this.template = SqsTemplate.newTemplate(sqsAsyncClient);
    }

    public SendResult<String> sendMessage(String queueName, String groupId, String message) {
        System.out.println("Sender: " + message);
        return template.send(to -> to
            .queue(queueName)
            .messageGroupId(groupId)
            .messageDeduplicationId(groupId)
            .payload(message));
    }

}

4. Message Listener

@Component
public class TransferListener {

    @SqsListener("${application.amazon.sqs.queue-name}")
    public void messageListener(String message) {
        System.out.println("Listener: " + message);
    }

}

 

Spring Cloud AWS 2.x에서는 deletion policy를 메서드마다 설정할 수 있었는데 해당 기능은 없어진것인지 어노테이션에 설정하는 필드가 존재하지 않습니다...

테스트 해보니 기본적인 deletion policy은 ON_SUCCESS로 메서드 내에서 에러 발생 시 메세지는 사라지지 않고 보존되었습니다.

이 부분은 deletion policy를 따로 설정할 수 있는지 좀 더 찾아보고 업데이트 하도록 하겠습니다.


5. Test

amazonSQSSender.sendMessage(queueName, UUID.randomUUID().toString(), "Send message test");

위에서 구축한 Sender를 통해 메세지를 보내면 Listener에서 받아지는 것을 확인할 수 있습니다.

 

 

피드백은 언제나 환영입니다!!

반응형