[AWS] SQS - 비용 최적화: 롱 폴링
SQS는 저렴하면서도 강력한 AWS의 관리형 서비스다.
근데 이것도 consume 형태에 따라서 좀 신중하게 쓸 필요는 있다.
그냥 Lambda 같은걸 트리거로 달아서 consume하는 형태라면 상관없는데, 직접 루프를 돌려서 api로 consume하는 것이라면 폴링 정책을 어떻게 하느냐에 따라서 비용 폭주가 발생할 수도, 적당히 나올 수도 있다.
숏폴링과 비용 문제
별다른 구성 없이 ReceiveMessage를 사용해서 Consume을 한다면, short polling으로 동작한다.

이게 무슨 말이냐면, 메시지가 없을때 그냥 API가 종료된다는 것이다.
이건 메세지가 많을 때는 문제가 없지만, 메세지가 없는 대기상태가 많을 경우에는 극심한 비효율을 낳을 수 있다.
보통 Queue의 Consume은 무한루프를 기반으로 이루어지고, SQS는 데이터 크기나 사용 시간이 아니라, 요청 횟수로 비용을 과금하기 때문이다.
그래서 메세지가 없을때 Consume 루프를 돌리면 뱅글뱅글 돌면서 API 요금을 과다하게 갉아먹는 문제가 발생할 수 있다.
롱 폴링
다행히도 SQS에서는 이에 대한 개선안을 제공한다.
그게 "WaitTimeSeconds"라는 이름으로 제공되는 롱 폴링 옵션이다.
WaitTimeSeconds은 초 단위의 시간값을 받고, 최대 20초까지 지정할 수 있다.
이걸 걸어두면 메세지가 들어오지 않았을 때는 API 연결을 끊지 않고 저 시간까지를 대기할 수 있다는 뜻이다.
연결이 길어진다고 해서 딱히 요금이 발생한다거나 하지는 않는다. 그냥 API를 연결한 채로 대기만 하는 것이다.
그 상태에서 메세지가 들어오면

그제서야 API가 종료되고 값이 반환된다.
참고: SQS 기본값
롱 폴링 대기시간은 API 호출에서만 줄 수 있는게 아니라, SQS 큐 설정 수준에서도 관리할 수 있다.
이런 식으로 직접 넣어주면, API에서 WaitTimeSeconds를 지정하지 않았을 경우에 저 값을 사용한다.
WaitTimeSeconds를 직접 지정해서 API를 호출한다면 저 SQS 설정은 무시된다. 그래서 기본값에 불과하다.
MaxNumberOfMessages로 배치 처리
MaxNumberOfMessages는 한번에 메세지를 몇개까지 가져올 수 있는지를 뜻하는 옵션이다.
1-10까지 설정 가능하다.
SQS 요금 산정 방식은 메세지를 가져오는 개수가 아니라 순수한 API 호출 횟수이므로, 가급적이면 메세지를 한번에 많이 받아와서 처리해버리는게 비용적으로 유리하다.
롱 폴링과 MaxNumberOfMessages
근데 문제는 MaxNumberOfMessages이라는 옵션 자체가, 좀 느슨한 형태로 구현되어있다는 것이다.
그래서 "숏 폴링을 사용한다면" 한번에 10, 20, 30개의 메세지가 들어오더라도, 10개가 한번에 들어오지 않을 확률이 있다. 그냥 빠르고 비용효율적으로(AWS 관점에서) 가져올 수 있도록 분산된 그룹에서 일부 하위 집합만 읽어들일 수 있기 때문이다.
롱 폴링을 적용하면 이런 유실 문제가 줄어들 수 있다.
참조
https://docs.aws.amazon.com/ko_kr/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-short-and-long-polling.html
https://stackoverflow.com/questions/60208266/sqs-maxnumberofmessages
https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_ReceiveMessage.html