애플리케이션을 개발하는 개발자는 루스커플링이라는 설계 원칙을 이용해 어플리케이션의 확장성과 신뢰성을 높인다. 루스커플링이란 불필요한 요소를 최소화해 하나의 서버에서 실행하는 단일 어플리케이션을 구현하되 어플리케이션 안에는 여러 컴포넌트들이 존재하는 마이크로서비스로 세분화 하는 것이다.마이크로서비스의 각 서비스들은 각기 다른 서버에서 실행된다. 그렇다면 이 각각의 서버는 어떻게 서로 소통할 수 있는걸까? 이것을 가능하게 해주는 것이 바로 SQS이다.
마이크로서비스, 즉 여러 서비스(서버,컴포넌트)들이 서로에게 메세지를 전송할 수 있도록 돕는 관리형 메세지 서비스다. 메세지 처리속도가 매우 빠르며, 고가용성 및 고탄력성이다.
SQS에서 처리해야 할 메세지를 담는 공간이 Queue다. 쉽게 말해 버퍼라고 생각하면 된다.
- 프로듀서 컴포넌트 : 큐에 메세지를 제공한다.
- 컨슈머 컨포넌트 : 큐의 메세지를 소비한다.
컨슈머가 메세지를 확인하더라도 메세지는 큐에 그대로 유지된다. 큐의 메세지 삭제여부는 컨슈머가 결정할 수 있다. 하지만 만약 컨슈머가 큐의 메세지를 가져와서 처리하는 동안 다른 컨슈머가 이 메세지를 또 가져와서 처리하면 중복처리가 발생한다.
따라서 가시성 중지기간을 설정해 컨슈머가 메세지를 처리하는 동안 이 메세지는 다른 컨슈머에게는 보이지 않게되는 기간을 설정하는 것이다.
📌default 30초, 최소 0초 ~ 최대 12시간
큐에 메세지를 넣을 때 큐마다 지연시간을 설정할 수 있다.
딜레이큐를 사용하면 컨슈머는 메세지를 즉시 보지 못하게 된다.
📌default 0초, 최대 15분
- Standard 큐 : 기본적으로 지원하는 큐 타입이며, 무제한의 처리성능을 제공하고 최대 12만개의 이동중인 메세지를 처리할 수 있다. 다만 순서와 무관하게 전달되므로 중복처리를 할 수 있는 기능이 있어야 한다.
- FIFO 큐 : 처리량이 초당 3천개며, 최대 2만개의 이동중인 메세지를 처리할 수 있다.
First-In,First-Out(FIFO)의 이름 처럼 먼저들어온 메세지가 먼저 처리되므로 순서가 존재해 중복처리를 따로 하지않아도 된다.
📌 FIFO 큐는 Standard 큐 보다 비싸다.
큐에서 메세지를 확인하기 위해서는 메세지가 도착했는지 도착여부를 조회해야하는데 이것을 가능하게 해주는 기능이 폴링이다. 폴링에는 숏폴링, 롱폴링이 있다.
- 숏폴링 : 기본값 폴링이며, 큐에 대기중인 메세지 내역만을 지연시간 없이 즉시 확인한다. 지연시간이 없기 때문에 메세지가 있어도 메세지가 없다는 응답을 받을 수 있다. 따라서 정확한 메세지 내역을 반환하려면 여러번 숏폴링을 수행해야 한다.
- 롱폴링 : 큐에서 대기중인 모든 메세지를 반환하며, 모든 큐 서버를 확인해야하기 때문에 지연시간이 20초가량 발생할 수 있다. 하지만 그만큼 숏폴링보다 수행해야하는 빈도수가 적기 때문에 비용효율적인 옵션이다
만약 큐의 메세지를 소비하는 EC2인스턴스(컨슈머)가 큐의 메세지를 처리하는 것을 계속 실패한다면, 이 메세지는 영원히 처리할 수 없을 것이다. 이러한 메세지를 데드레터라 하며, 데드레터큐를 만들어 이 데드레터를 따로 보관한다. 이후 maxReceiveCount속성을 이용해 메세지의 최대 인출 시도 횟수를 설정한다.
만약 maxReceiveCount=5라면, 인스턴스가 메세지를 꺼내 처리하는 횟수가 5번을 넘는다면 데드레터큐로 옮긴다.
📌 데드레큐의 보유기간은 큐의 보유기간에 종속된다. 즉 큐의 보유기간이 7일인 상황에서 6일이 지난다음 데드레터큐로 옮겨진다면 1일뒤에 데드레터큐에서 삭제된다.
팬아웃이란 SNS뒤에 여러개의 큐를 배치하는 형태로 각각의 큐마다 다른 작업을 수행할 수 있다. 즉 처리속도가 매우 빨라지는 장점이 있다. 팬아웃은 Kinesis에도 적용할 수 있는데 이것은 추후 포스터에서 다루어 볼 예정이다.
💡 만약 SQS-FIFO 타입을 선택했다면, SNS-FIFO 타입이여야 한다.
SQS에 컨슈머로 EC2를 하나이상 배치하고 EC2가 큐에 있는 데이터(메세지)를 가져와 처리할 수 있다. 이때 중요한점은 EC2가 폴링을 통해 메세지를 확인하고 가져와서 처리하는 동안 큐에 있는 해당 메세지는 사라지는 것이 아니라 그대로 있고, EC2가 처리를 완료하면 DELETEMessage액션을 통해 그제서야 큐에 있는 메세지가 사라진다. 만약 EC2가 처리를 실패한다면 EC2는 다시 큐에 있는 해당 메세지를 폴링해서 가져와 처리한다.
큐가 가지고 있는 메세지의 개수를 CLOUDWATCH의 METRIC으로 설정해 오토스케일링의 지표로 설정 할 수 있다. 예시로 CLOUDWATCH가 큐를 계속 모니터링하다가 큐의 메세지가 많아져서 일정 수준을 넘어가면 오토스케일링 액션을 수행하고 EC2는 이 액션에 따라 자동확장한다.
💡 위의 활용처럼 큐는 '분리', '마이크로 서비스', '가용성', '데이터 분실 위험' , '탄력성'에 잘 어울리는 서비스이다.
이번 포스팅에서는 마이크로서비스간 통신을 어떻게 가능하게 해주는지 알아보았다. 하지만 큐는 버퍼이고 '실시간' 으로 컴포넌트간 통신을 가능하게 해주는데는 적합한 서비스가 아니라는 생각이 들었다. 다음 포스팅에서는 마이크로서비스에서 서비스간의 실시간 통신을 가능하게 해주는 Kinesis에 대해서 다루어 볼 예정이다.