AWS SQS
- SQS의 핵심은 대기열이다.
- SQS는 간단한 대기 서비스이고, 대기열에는 메시지를 포함한다.
- 메시지를 담기 위해서는 무언가 SQS 대기열에 메시지를 전송해야 하는데 SQS 대기열에 메시지를 보내는 주체를 '생산자'라고 한다.
- 생산자는 한 개일 수도 그 이상일 수도 있다. - 여러 생산자가 여러 개의 메시지를 SQS 대기열에 보내게 할 수 있다.
- 메시지는 무엇이든 상관없다. 가령 '오더를 처리해라'일 수도 있고, '비디오를 처리해라'일 수도 있다. - 생성한 모든 메시지는 대기열에 들어간다. 그런 다음 대기열에서 메시지를 처리하고 수신해야 하는 대상을 '소비자'라고 한다.
- 소비자는 대기열에서 메시지를 폴링하는데 이는 대기열에게 소비자 앞으로 온 메시지가 있는지를 물어보는 것이다. 만일 대기열에 메시지가 있으면 소비자는 이 메시지를 폴링해서 정보를 얻는다. 그리고 그 메시지로 처리를 하고 대기열에서 그 메시지를 삭제한다.
- 여러 소비자가 SQS 대기열에서 메시지를 소비할 수 있도록 할 수도 있다.
- 대기열 서비스는 생산자와 소비자 사이를 분리하는 버퍼 역할을 한다.
SQS - Standard Queue
- 가장 먼저 제공되는 것은 표준 대기열용 Amazon SQS이다.
- SQS는 AWS에서 제공하는 가장 오래도니 서비스이다. 그래서 작동 방식이 확실하게 구축되어 있다.
- 완전 관리형 서비스이며 애플리케이션을 분리하는데 사용된다.
- SQS의 특별한 점은 '무제한 처리량'을 얻을 수 있다는 것이다.
- 즉, 초당 원하는만큼 메시지를 보낼 수 있고, 대기열에도 원하는 만큼 메시지를 포함시킬 수 있다.
- 처리량에 제한이 없고 대기열에 있는 메시지 수에도 제한이 없다. - 각 메시지는 수명이 짧은데, 메시지는 기본값으로 4일 동안 대기열에 남아 있고 대기열에 있을 수 있는 최대 시간은 14일이다.
- 즉, 대기열에 메시지를 보내자마자 소비자가 읽고 해당 보존 기간 내에 처리한 후 대기열에서 삭제해야 한다. 그렇지 않으면 소실된다.
- 지연 시간이 짧아서 SQS는 메시지를 보내거나 SQS에서 메시지를 읽을 때마다 게시 및 수신 시 10밀리초 이내로 매우 빠르게 응답을 받게 된다. - SQS의 메시지는 작아야 한다.
- 전송된 메시지당 256KB 미만이어야 한다.
- SQS는 대기열 서비스이므로 높은 처리량, 높은 볼륨 등이 있어서 중복 메시지가 있을 수 있다.
: 예를 들어, 메시지가 두 번 전송되는 경우가 있으므로 적어도 한 번의 전송이라고 하는 것이다.
SQS - Producing Messages(메시지 생산자)
- 최대 256KB의 메시지가 생산자에 의해 SQS로 전송된다.
- 어떻게 보낼까?
- 생산자는 SDK 소프트웨어 개발키트를 사용하여 SQS에 메시지를 보낸다.
- SQS에 메시지를 보내는 API를 SendMessage라고 한다. - 메시지가 작성되면 소비자가 해당 메시지를 읽고 삭제할 때까지 SQS 대기열에 유지된다.
- 메시지가 삭제됐다는 것은 메시지가 처리됐다는 뜻이다. - 메시지 생성의 어떨 때 사용할까?
- 예를 들어, 패킷과 같은 오더를 처리한 다음 센터로 배송하려고 한다. 따라서 원하는 시간에 이 작업을 수행하여 오더 ID, 고객 ID와 원한느 속성 등의 일부 정보가 포함된 메시지를 SQS 대기열로 보낸다. 주소도 원하는 속성에 들어갈 수 있고, 애플리케이션 권한에 있는 소비자는 해당 메시지 자체를 처리해야 한다.
SQS - Consuming Messages(메시지 소비자)
- 소비자는 일부 코드로 작성해야 하는 애플리케이션이고 이러한 애플리케이션은 EC2 인스턴스 즉, AWS상의 가상 서버에서 실행될 수 있다.
- 원하는 경우 자체 온프레미스 서버에서 실행할 수도 있고, AWS Lamba의 람다 함수에서 실행할 수도 있다.
- EC2 인스턴스에 대한 간단한 사용 사례로 보면, 대기열에는 소비자가 있고 소비자는 SQS 메시지를 폴링한다. 즉, 소비자가 대기열에 자신의 앞으로 온 메시지가 있는지를 묻는다. 그리고 소비자는 아마 한 번에 최대 10개의 메세지를 받을 것이다. SQS 대기열에 메세지가 있으면 '여기 너를 기다리는 메세지가 있어'라는 유효한 응답을 받을 것이다.
- 우리의 코드인 소비자는 이 메시지들을 처리할 책임이 있다. RDS 데이터베이스에 오더를 입력하는 경우를 생각해 보자. 즉, 각 오더들을 RDS 데이터베이스에 삽입하면 물론 이 작업은 코딩으로 이루어지겠지만, 그렇게 삽입하면 이 메시지들이 수신되어 처리됐기 때문에 Amazon RDS 데이터베이스로 삽입된다. 그러면 소비자가 이 메시지들을 DeleteMessage API로 대기열에서 삭제한다. 그러면 다른 소비자들이 이 메세지를 볼 수 없게 된다. 그러면 메시지 처리가 완료된다.
- 이를 확장해 보면 여러 소비자를 동시에 가질 수 있는데 밑에서 확인해보자.
SQS - Multiple EC2 Instances Consumers
- SQS 대기열은 메세지를 동시에 수신하고 처리할 소비자를 여러 개 가질 수 있다.
- 위의 EC2 인스턴스 세가지가 있고, 각 소비자는 poll 함수를 호출하여 다른 메시지 세트를 수신하게 된다.
- 만일 메시지가 소비자에 의해 충분히 빠르게 처리되지 않으면 다른 소비자가 수신하게 된다. 그래서 적어도 한번은 전송이 된다고 하는 것이다. 그리고 이 부분이 최선의 노력으로 메시지 순서 지정을 하는 이유이다.
- 소비자가 메시지를 처리하면 메시지를 삭제해야 한다. 그렇지 않으면 다른 소비자가 메시지를 보게 된다.
- SQS 대기열에서 더 많은 메시지가 있어서 처리량을 늘려야 하면 소비자를 추가하고 수평 확장을 수행해서 처리량을 개선할 수 있다.
SQS with Auto Scaling Group (ASG)
- 위의 이미지는 ASG와 더불어 SQS를 사용하는 완벽한 사례이다.
- 소비자가 ASG의 내부에서 EC2 인스턴스를 실행하고 SQS 대기열에서 메시지를 폴링한다.
- ASG는 일종의 지표에 따라 확장되어야 하는데 우리가 사용할 수 있는 지표는 대기열의 길이이다. "ApproximateNumberOfMessages"라고 한다. 이는 모든 SQS 대기열에서 쓸 수 있는 CloudWatch 지표이다. - 알림을 설정할 수도 있는데 대기열의 길이가 특정 수준을 넘어가면 CloudWatch Alarm을 설정하면 된다.
- 이 알람은 오토 스케일링 그룹의 용량을 X만큼 증가시킨다. 그러면 더 많은 메시지가 SQS 대기열에 있게 된다. - 만일 웹 사이트에 오더가 폭주했다거나 해서 오토 스케일링 그룹이 더 많은 EC2 인스턴스를 제공하면 메시지들을 더 높은 처리량으로 처리할 수 있다.
SQS to decouple between application tiers
- SQS는 애플리케이션 계층 간에 분리를 위해 사용된다. 가령 비디오를 처리하는 애플리케이션이 있다고 가정해보자.
- 프론트엔드라는 큰 애플리케이션이 있는데, 프론트엔드가 요청을 받고 비디오가 처리되어아 할 때, 프론트엔드가 처리를 한 후 S3 버킷에 삽입한다.
- 문제는 처리 시간이 매우 오래 걸릴 수 있고, 프론트엔드에서 이를 처리하면 웹사이트의 속도가 느려질 수 있단느 것이다. 대산 애플리케이션을 분리하여 파일 처리 요청과 실제 파일 처리가 서로 다른 애플리케이션에서 발생할 수 있도록 할 수 있다.
- 파일 처리 요청을 받을 때마다, SQS 대기열로 메시지를 전송하는 것이다. 그러면 처리 요청을 할 때, 해당 파일은 SQS 대기열에 있게된다.
- 자체 오토 스케일링 그룹에 속할 백엔드 처리 애플리케이션이라는 두 번째 처리 계층을 생성할 수 있다. 이 애플리케이션이 메세지를 수신하고 비디오를 처리하고 S3 버킷에 이를 삽입할 것이다.
- 위의 아키텍처에서 볼 수 있듯이 그에 따라 프론트엔드를 확장할 수 있고, 그에 따라 백엔드도 확장할 수 있지만 독립적으로 확장할 수 있다.
- SQS 대기열은 처리량이 무제한이고, 대기열 측면에서 메시지 수에 제한이 없기 때문에 정말 안전하다. 강력하고 확장 가능한 유형의 아키텍처이다.
- 프론트엔드의 경우, 최적의 유형의 EC2 인스턴스 또는 아키텍처를 프론트엔드에 사용할 수 있다.
- 백엔드의 경우, 비디오 처리를 수행할 때 그래픽 처리 장치인 GPU가 있는 일부 EC2 인스턴스를 사용할 수 있다.이러한 유형의 인스턴스가 워크로드를 수행하는 데에 최적이기 때문이다.
AWS SQS - Security
- HTTPS API를 사용하여 메시지를 보내고 생성함으로써 비행 중 암호화를 하고 KMS 키를 사용하여 미사용 암호화를 얻고 원한다면 클라이언트 측 암호화를 할 수도 있는데 이는 클라이언트가 자체적으로 암호화 및 암호 해독을 수행해야 함을 의미한다.
- 액세스 제어를 위해 IAM 정책은 SQS API에 대한 액세스를 규제할 수 있고, S3 버킷 정책과 유사한 SQS 액세스 정책도 있다.
- SQS 대기열에 대한 교차 계정 액세스를 수행하려는 경우나 곧 배울 SNS 혹은 Amazon S3 같은 다른 서비스가 SQS 대기열에 S3 이벤트 같은 것을 쓸 수 있또록 허용하려는 경우에 매우 유용하다.
SQS - Message Visibility Timeout(메시지 가시성 시간 초과)
- 소비자가 메시지를 폴링하면 그 메시지는 다른 소비자들에게 보이지 않게 된다.
- 위의 예시를 같이 살펴보자.
- 왼쪽에서 오른쪽으로 가는 시간이 있고, 컨슈머가 ReceiveMessage 요청을 하고 있고, 대기열에서 메시지가 반환된다. 그럼 이제 가시성 시간이 초과가 시작된다. 기본 값으로 메시지 가시성 시간 초과는 30초이다. 그 말은 이 30초 동안 메시지가 처리되어야 한다는 것이다. 그러면 동일한 혹은 다른 소비자가 메시지 요청 API를 호출하면 메시지가 반환되지 않는다. 시간 초과 기간 내에 또 다른 요청이 들어와도 메시지가 반환되지 않는다. 즉, 가시성 시간 초과 기간 내에서는 그 매시지는 다른 소비자들에게 보이지 않는다. 가시성 시간 초과가 경과되고 메시지가 삭제되지 않았다면 메시지는 대기열에 다시 넣는다. 그러면 다른 소비자 또는 동일한 소비자가 또 ReceiveMessage API 호출을 하면 이전의 그 메시지를 또 받게 된다. 보시다시피 메시지를 받는 동안 가시성 시간 초과 기간 동안 보이지 않게 된다.
- 위의 도표를 보면 가시성 시간 초과 기간 내에 메시지를 처리하지 않으면 메시지가 두 번 처리될 수도 있다는 것을 알 수 있다.
- 두 명의 다른 소비자가 수신하거나 동일한 소비자가 두 번 수신하기 때문이다.
- 만일 소비자가 메시지를 적극적으로 처리하고 있지만 메시지를 처리하는 데 시간이 더 필요하다는 것을 알고 있는데 메시지를 처리하지 않아 가시성 시간 초과 기간을 벗어날 때를 위해 ChangeMessageVisibility라는 API가 있다. 즉, 소비자가 메시지를 처리하는 데 시간이 더 필요하다는 것을 알고 있고 해당 메시지를 두 번 처리하고 싶지 않다면 소비자는 ChangeMessageVisibility API를 호출하여 SQS에 알려야 한다. - 메시지 가시성 시간 초과를 어떻게 설정해야 할까?
- 기본값으로 매우 높은 값, 예를 들어 시간으로 설정하면 소비자가 충돌했을 때 이 메시지가 다시 나타날 때까지
즉, SQS 대기열에 보이기까지 몇 시간이 걸린다. 몇초와 같이 매우 낮은 값으로 설정하면 소비자가 어떤 이유로든 해당 메시지를 처리할 시간이 충분하지 않으면 다른 소비자가 메시지를 여러 번 읽을 것이며 중복 처리될 수 있다. - 가시성 시간 초과는 애플리케이션에 합당한 것으로 설정되어야 하고 소비자는 시간이 조금 더 필요하다는 것을 알면 ChangeMessageVisibility API를 호출하도록 프로그래밍해야 한다. 그러면 더 많은 시간을 확보하고 해당 가시성 시간 초과 기간을 늘릴 수 있다.
SQS - Long Polling
- 예를 들어, 소비자가 대기열에 메시지를 요청하는데 대기열에 아무것도 없다면 메시지 도착을 기다리면 된다.
= 이것을 "Long Polling(롱 폴링)"이라고 한다. - 이렇게 하는 이유는 두가지이다.
- 첫 번째는 지연시간을 줄이기 위해서
- 두 번째는 SQS로 보내는 API 호출 숫자를 줄이기 위해서이다. - 구성하는 방법도 두가지이다.
- 대기열 레벨에서 구성하여 폴링하는 아무 소비자로부터 롱 폴링을 활성화하는 방법
- WaitTimeSeconds를 지정함으로 소비자가 스스로 롱 폴링을 하도록 선택
- 위의 이미지로 작동방식을 알아보자.
- 비어있는 SQS 대기열이 있고, 소비자가 대기열에 폴링한다. 최대 20초 동안 폴링 할 것이다.
- 만약 대기열이 비어 있다면 그냥 기다리겠다는 것이고, 좀 기다려도 좋다는 것이다. - 그러닥 메시지가 발생할 때 즉, 메시지가 대기열에 막 도착할 때, 소비자가 여전히 롱 폴링 중이라면, 자동적으로 그 메시지가 소비자에게 전송된다. 이때의 지연 시간은 짧아서 자동으로 최대한 빨리 받게 된다.
- 롱 폴링은 SQS로의 API 호출 숫자를 줄인다. 그러면서 애플리케이션의 효율성과 대기 시간을 증가시킨다. 그래서 1초부터 20초 사이로 구성이 가능하다.
- SQS 대기열에 대한 API 호출 수를 최적화하고 지연 시간을 줄이는 방법을 묻는다면 롱 폴링을 떠올리면 좋다.
SQS - FIFO Queue
- SQS에서 사용 가능한 다른 종류의 대기열 즉, Amazon SQS FIFO 대기열이 있다.
- FIFO = 선입선출 - 대기열에 첫 번째로 도착한 메시지가 대기열을 떠날 때도 첫 번째가 되도록 대기열 내의 순서가 정렬된다는 의미이다.
- 표준 대기열보다 순서가 더 확실히 보장되는 것이다. - 위의 SQS 대기열로 메시지를 보내는 예시를 보자.
- 첫 번째, 두 번째, 세 번째 그리고 네 번째 메시지를 보내고, SQS FIFO 대기열은 소비자가 SQS FIFO 대기열로부터 메시지를 불러올 때 정확히 동일한 순서로 메시지를 받게 해준다. - 순서를 확실히 보장하기 때문에 이 SQS 대기열의 처리량에는 제한이 있다.
- 묶음이 아닐 경우에는 초당 300개의 메시지를 처리하고 메시지를 묶음으로 보낸다면 그 처리량은 초당 3,000개가 된다. - 중복을 제거하도록 해주는 SQS FIFO 대기열의 기능으로 인해 정확히 한 번만 보낼 수 있게 해준다.
- 메시지가 소비자에 의해 순서대로 처리된다는 것을 알고 있기 때문에 분리가 발생하거나 메시지의 순서를 유지할 필요가 있을 때 FIFO 대기열을 사용하면 된다.
SQS with Auto Scaling Group (ASG)
- 위에서 설명했듯이, 오토 스케일링 그룹에 SQS 대기열을 사용할 수 있다고 했는데 이번에는 그 방법과 사용에 따른 패턴에 대해 알아보자.
- SQS 대기열과 오토 스케일링 그룹이 있을 때, ASG 내의 EC2 인스턴스에 메시지를 SQS 대기열에서 폴링한다. 이는 오토 스케일링 그룹을 자동으로 대기열 크기에 따라 확장시키기 위함으로 CloudWatch 지표인 대기열 길이를 보고 결정할 수 있다.
- ApproximateNumberOfMessages라고 하는 이 지표는 대기열에 몇 개의 메시지가 남아 있는지를 표시한다. 이를 기반으로 경보를 지정할 수 있는데 가령 이 지표가 1,000을 넘는 경우 1,000개의 메시지가 대기열에서 처리를 기다리고 있다는 뜻으로 처리에 지연이 발생하고 있음을 파악할 수 있다.
따라서 경보를 생성하여 1,000개의 메시지가 대기 중임을 경보를 통해 알리면 이 경보가 EC2 인스턴스가 충분하지 않음을 근거로 오토 스케일링 그룹에 확장 동작을 트리거한다. 이렇게 하면 오토 스케일링 그룹에 더 많은 EC2 인스턴스가 추가되며 확장이 이루어져 메시지가 훨씬 더 빨리 처리된다. 동시에 SQS 대기열의 크기는 줄어들어 이에 대한 축소 또는 실행된다.
If the load is too big, some transactions may be lost
(부하가 너무 크면 일부 트랜잭션이 손실될 수 있다.)
- 가령 우리가 대대적인 세일 행사를 진행 중이라고 해보자. 매우 엄청 큰 광고도 이루어졌고 수많은 고객이 주문할 것이다.
- 이 때, 해당 주문은 여러 유형의 데이터베이스에 저장될 수 있는데 Amazon RDS나 OLTP 유형 데이터베이스를 필요로 하는 경우라면 Amazon Aurora NoSQL 유형 데이터베이스가 필요하면 Amazno DynamoDB에 저장할 수 있다. 트랜잭션 내역은 상당히 빠른 속도로 순식간에 RDS나 Aurora에 쓰일 것이다.
- 우리의 애플리케이션이 주문 즉, 요청을 처리할텐데 데이터베이스가 오버로드 되는 등 모종의 이유로 특정 트랜잭션에 오류가 발생한다면 해당 고객 트랜잭션은 유실되고 이는 우리 비즈니스에 전혀 좋지 않다.
- 이 문제를 어떻게 해결해야될까? 밑으로 가보자.
SQS as a buffer to database writes
(쓰기 대상 데이터베이스에서 버퍼로서의 SQS)
- 쓰기 대상 데이터베이스에서 SQS를 버퍼로 사용할 수 있다.
- 위의 동일한 데이터베이스와 프론트엔드 애플리케이션이 있다고 하면 데이터베이스에 바로 요청을 쓴느 대신 애플리케이션이 요청, 즉 트랜잭션을 일명 무한히 확장 가능한 SQS 대기열에 먼저 쓰는 방법이 있다. 이렇게 하면 처리량 문제가 발생하지 않는다.
- 애플리케이션에 요청이 전송되고 이 요청은 메시지로 대기열에 안착하는데 이는 곧 모든 트랜잭션, 즉 모든 요청이 SQS 대기열에 메시지로서 전달된다는 뜻이다. 이렇게 하면 단 하나도 유실되는 요청이 없다. 요청은 지속적으로 SQS 대기열에 저장될 것이다.
- 위의 이미지에서 또 다른 오토 스케일링 그룹으로 메시지를 대기열에서 제외할 수도 있다. 오토 스케일링 그룹의 유일한 목적은 메시지를 수신해서 데이터베이스로 삽입하는 작업이다.
메시지가 데이터베이스에 삽입되고 나면 기존 SQS 대기열에서 해당 메시지를 삭제한다. - 이렇게 SQS를 버퍼로 사용하여 모든 트랜잭션이 데이터베이스에 쓰이도록 확인할 수 있다. 이 패턴은 클라이언트에게 따로 데이터베이스에 쓰였다는 확인을 전송할 필요가 없을 때만 사용 가능하다.
- 하지만 SQS 대기열에 쓰기 작업이 일어났다는 것만으로도 결국 데이터베이스에 요청이 쓰일 테니 일종의 확인을 한 셈이다.
SQS to decouple between application tiers
(애플리케이션 계층 간 분리를 위한 SQS)
- 데이터베이스 쓰기 간 분리와 애플리케이션 티어 간 분리에 활용되는데 애플리케이션이 요청을 전달받고 처리한 후 응답을 재전송하는 대신 이 과정을 분리하여 모든 요청을 프론트엔드 웹 애플리케이션에서 받고 해당 요청을 SQS 대기열로 전송하여 백엔드 처리 작업이 메시지를 전달받은 다음 준비되면 메시지를 처리하고 필요에 따라 스케일링하는 것이다.
'AWS(Amazon Web Service)' 카테고리의 다른 글
[AWS] AWS Integration & Messaging - SNS + SQS : Fan Out (0) | 2024.11.24 |
---|---|
[AWS] AWS Integration & Messaging - SNS (1) | 2024.11.23 |
[AWS] AWS Integration & Messaging (0) | 2024.11.21 |
[AWS] 모든 AWS 스토리지 옵션 비교 (0) | 2024.11.20 |
[AWS] AWS 스토리지 추가 기능 - AWS DataSync (2) | 2024.11.19 |