AWS 통합 및 메세징 기법
이 섹션에서는 애플리케이션을 여러 개 배포하려고 할 때, 커뮤니케이션을 하는 방법을 배운다.
동기 방식
- 두 애플리케이션을 직접적으로 연결한다.
비동기 방식
- 큐를 사용해 애플리케이션간 메세지를 주고받는다.
큐 모델에서는 SQS를 사용하고
pub/sub 모델 (구독 모델, publish 하면 구독자들에게 모든 메세지 전달)에서는 SNS를 사용하고
실시간 스트리밍 모델에선 Kinesis를 사용한다.
이제 애플리케이션을 분리해서 독립적으로 확장할 수 있다.
SQS
- SQS는 큐다.
- 큐에 메시지를 전송한다. 전송된 메시지는 대기열에 들어간다.
- 여러 곳에서 동시에 큐에 메시지를 전송할 수 있다.
- 메시지를 받을 대상이 큐에게 자신 앞으로 온 메시지가 있는지 물어본다.
- 만약 메시지가 있다면 폴링해서 처리한다.
- 폴링된 메시지는 삭제된다.
SQS - Standard Queue
- AWS 에서 제공하는 가장 오래된 서비스다.
- 완전히 관리되는 서비스이며 애플리케이션을 분리하는 데 사용된다.
- 무제한 처리량을 얻을 수 있다.
- 원하는 만큼의 메시지를 큐로 보낼 수 있다.
- 처리량에 제한이 없고 대기열에 있는 메시지 수에도 제한이 없다.
- 각 메시지는 수명이 짧다.
- 메시지는 기본값으로 4일 동안 대기열에 남아있고, 최대 14일 동안 남아있을 수 있다.
- 보존 기간내에 메시지를 처리하고 삭제해야 한다.
- 그렇지 않으면 메시지는 소실된다.
- 지연 시간이 짧아서 SQS는 메시지를 보내거나 SQS에서 메시지를 읽을 때마다
10ms 이내로 응답을 받게된다. - SQS로 보내는 메시지는 개당 최대 256kb까지 가능하다.
- 중복되어 전송되는 메시지가 존재할 수도 있다.
- 순서에 맞지 않는 메시지가 존재할 수도 있다. (하지만 순서가 맞게 최선을 다할 것이다.)
SQS - 메시지 전송자
- 최대 256kb의 메시지가 SQS로 전송된다.
- 전송자는 SDK 키트를 사용하여 SQS로 메시지를 보낸다. (sendMessage API)
- 수신자가 메시지를 읽고 삭제할 때까지 SQS 대기열에 유지된다.
- 유지는 기본값 4일, 최대 14일
- 주문 프로세스를 예시로 들 수 있다.
- 주문이 발생했을 때, order id, customer id, 주소 등등의 정보를 SQS로 보낸다.
- 이후 수신자가 정보를 받고 처리한다.
SQS - 메시지 소비자 (수신자)
- 소비자 예시 (Ec2, Servers, Lambda ,,)
- 만약 SQS에 대기 중인 메시지가 있다면, 대기중인 메시지가 있다는 응답을 받는다.
- 소비자는 한 번에 최대 10개의 메시지를 받을 수 있다.
- 소비자가 주문에 대한 메시지를 받는다면, 데이터베이스에서 원하는 작업을 한 후,
SQS에 Delete Message API를 호출에 메시지를 대기열에서 삭제한다. - SQS는 메시지를 수신할 소비자를 동시에 여러 명 둘 수 있다.
- 각 소비자는 큐에서 메시지를 폴링한다.
- 만일 소비자에 의해 충분히 빠르게 처리되지 않는다면, 다른 소비자가 수신하게 된다.
- 따라서 적어도 한 번은 전송이 된다라고, SQS에서 명시하는 것이다.
- 그리고 이것이 최선의 노력으로 메시지 순서 지정을 한다는 이유이다.
- 순서가 올바르지 않을 수 있다는 이유
- 소비자가 메시지를 처리하면 반드시 메시지를 삭제해야 한다.
그렇지 않다면 위의 이유 때문에 다른 소비자에게 메시지가 전송될 수도 있다.
- SQS 대기열에 너무 많은 메시지가 있어 처리량을 늘려야 한다면,
소비자를 추가하고 수평 확장을 수행해서 처리량을 개선해야 한다.
SQS with ASG
- 소비자가 ASG 내부에서 EC2 인스턴스를 실행하고 SQS에서 메시지를 풀링한다.
- 여기서 대기열의 길이를 ASG 지표로 선정할 수 있다.
- CloudWatch Metric - Queue Length에서
ApproximateNumberOfMessages를 사용하면 대기열의 길이를 알 수 있다.- 알림을 설정할 수도 있는데, 대기열의 길이가 특정 수준을 넘어가면, 알림을 보내
ASG 용량을 증가시킬 수 있다.
- 알림을 설정할 수도 있는데, 대기열의 길이가 특정 수준을 넘어가면, 알림을 보내
SQS - 계층간 분리를 위한 SQS
- 비디오를 처리하는 애플리케이션이 있다고 해보자, 프론트에서 요청을 받고
비디오를 처리한 후 S3 버킷에 삽입한다.- 여기서 처리 시간이 매우 오래 걸릴 수 있고, 프론트에서 이를 처리하려면 웹사이트 속도가 느려질 수 있다.
- 애플리케이션을 분리해서 실제 파일 처리를 다른 애플리케이션에 수행하도록 할 수 있다.
- 비디오 처리 요청이 들어올 때마다 SQS 대기열로 메시지를 전송한다.
- 이후 백엔드에서 큐에 들어있는 메시지를 수신해서 처리한 후 S3에 삽입하면
웹사이트 속도가 지연될 일이 없다.
- 메시지 수에 제한이 없기 때문에 매우 강력한 기능이다.
SQS - Security
- HTTPS 프로토콜을 사용하여 전송 중 암호화를 한다.
- KMS 키를 사용하여 대기 상황에서 암호화를 할 수 있다.
- 클라이언트 측 암호화를 할 수도 있다. SQS에서 지원은 안 한다.
- Access Controls를 위해 IAM 정책은 SQS API를 제한할 수 있다.
- S3 버킷 정책과 유사한 SQS Access Policies가 있다.
- 교차 계정 액세스나
다른 서비스가 SQS 대기열에 S3 이벤트 같은 것을 쓸 수 있도록 하는 경우에 매우 유용하다.
- 교차 계정 액세스나
SQS - queue Access Policy
- S3 버킷 정책과 굉장히 유사하다. Json 으로 작성한다.
- Cross Account Access:
- 어떤 계정에 SQS가 있고 다른 계정의 EC2가 해당 SQS에 액세스해야 한다고 해보자
- EC2 가 다른 계정의 큐에서 메시지를 가져오려면,
SQS 액세스 정책에 다음과 같이 다른 계정의 접근을 허용해줘야 한다.
- principal 즉 적용 대상에 EC2 인스턴스가 있는 다른 계정이 포함됐다.
다른 사용 사례를 살펴보자
- publish S3 Event Notifications To SQS queue
- S3의 이벤트 알림을 큐에 넣는 것이다.
- 예를 들어 S3 버킷에 객체가 업로드가 됐을 때 SQS 대기열에 자동으로 메시지를 보낸다.
- SQS 대기열은 S3 버킷이 메시지를 보낼 수 있는 권한을 설정해야 한다.
SQS - Message Visibility Timeout
- 소비자가 메시지를 폴링하면, 해당 메시지가 처리될 동안 다른 소비자에게
해당 메시지가 보여서는 안 된다. - 이를 위해 특정 소비자가 메시지를 폴링해서 처리할 시간 동안 다른 소비자에게
메시지를 보여주지 않는 시간을 Visibility Timeout이라 한다. - 기본 값으로 30초로 설정돼있다.
- 이 말은 소비자가 메시지를 폴링하면 30초 이내로 메시지를 처리하고 삭제해야 된다는 의미다.
- 이 visibility timeout 시간 동안 다른 소비자가 메시지 요청 API를 호출하면
메시지가 반환되지 않는다.
- 만약 시간이 모두 흘렀는데도, 메시지가 삭제되지 않았다면 메시지는 다시 대기열 안에 들어간다.
- 이를 통해, visibility timeout 시간 안에, 메시지를 처리하지 않으면
메시지가 두 번 처리될 수도 있다는 걸 알 수 있다. - 만약 소비자가 메시지를 열심히 처리하고 있는데 다른 소비자에게 메시지가 가면
심각한 오류를 초래할 수 있으므로, 이를 대비한 API가 존재한다.
- ChangeMessageVisibility 라는 API다.
- 메시지를 처리하는데 시간이 더 필요하다면 위의 API를 호출해 시간을 늘리면 된다.
- 해당 시간을 매우 높은 값으로 설정한다면, 오류가 났을 때 다시 처리하는데 오랜 시간이 걸릴 것이다.
- 해당 시간을 매우 짧은 값으로 설정한다면, 두 번 처리될 확률이 높아진다.
- 따라서 적절한 시간으로 설정하는 것이 중요하다.
SQS - Dead Letter Queue (DLQ)
- 소비자가 제한 시간 내에 메시지를 처리하지 못했을 경우, 다시 큐로 돌아간다.
- 하지만 이런 일이 한 메시지에서 계속 발생한다면, 이건 메시지에 문제가 있다는 것이다.
- 그래서 이 반복 횟수에 임곗값을 둘 수 있다.
- 특정 횟수가 넘어갔을 경우, DLQ 즉 실패 메시지 대기열로 보낸다.
- 실패 메시지 대기열은 디버깅 시 아주 유용하다.
- 실패 메시지 대기열도 SQS 대기열이어서 메시지 처리를 해야하나,
적어도 그동안 문제를 파악할 시간이 생긴다.
- 실패 메시지 대기열도 SQS 대기열이어서 메시지 처리를 해야하나,
- FIFO 대기열은 실패 메시지 대기열도 FIFO 대기열이어야 한다.
- 표준 대기열 역시 실패 메시지 대기열이 표준 대기열이어야 한다.
- 실패 메시지 대기열의 메시지들은 대기열에서 만료되기 전에 처리해야 한다.
- 따라서 보관 기간을 14일 정도로 길게 설정하는 것이 좋다.
SQS DLQ - Redrive to Source
- 실패 메시지 대기열에 있는 메시지를 다시 소비해서 어떤 문제가 있었는지 파악하게 도와주는 역할이다.
- 문제 파악 외에도, 오류 발생 후 실패 메시지 대기열로 메시지가 이동했을 때
디버그를 통해 서비스의 코드를 고쳤다면,
해당 실패 메시지를 다시 원래 큐로 돌려서 처리하면 된다.- 이 때도, Redrive to Source를 활용해 기존 Source 큐로 이동시키면 된다.
SQS - Delay Queue
- 소비자들이 즉각적으로 메시지를 보지 못하도록 메시지를 지연시키는 기능이다.
- 최대 15분까지 지연 가능하다.
- 기본 값은 0초다.
- 모든 메시지에 적용시키려면 큐 단위에서 설정하면 되고
- 메시지 별로 지연 시간을 다르게 지정하려면,
DelaySeconds 파라미터를 지정해 보내면 된다.
- 메시지 별로 지연 시간을 다르게 지정하려면,
- 만약 30초로 설정하면 소비자는30초 후에 메시지를 수신할 수 있다.
SQS - Long Polling
- 소비자가 큐에다 메시지를 요청할 때, 대기열이 비어있다면 메시지가 도착할 때까지 기다리게 할 수 있다.
이를 롱 폴링이라 한다. - 기다리는 도중에 메시지가 큐에 도착하면 소비자는 메시지를 바로 수신한다.
- SQS로 보내는 API 호출의 수를 줄일 수 있다는 장점이 있다.
- 더불어 메시지가 대기열에 도착하자마자 수신하니 응답 속도도 빠르다.
- 롱 폴링 시간은 1~20초로 설정할 수 있다.
- 보통 20초를 선호한다.
- 시험에서 소비자가 큐로 너무 많은 API 호출을 보내서 비용이 발생하고,
CPU 연산이 늘어난다는 문제를 본다면 롱 폴링을 선선택해야 한다. - 롱 폴링은 큐 레벨에서 활성화 하거나,
소비자가 폴링을 위해 SQS 대기열로 API 호출을 보낼 때
WaitTimeSeconds 라는 파라미터를 사용해 설정할 수도 있다.
SQS - Extended Client
- 메시지의 최대 크기제한은 256kb이다.
- 어떻게 하면 1GB 정도의 대용량 메시지를 큐에 보낼 수 있을까?
- SQS Extended Client라는 자바 라이브러리를 사용할수 있다.
- 기본 개념은 대용량 메시지를 S3에 담는 것이다.
- 그리고 SQS에는 S3 버킷에 들어있는 대용량 메시지에 대한 포인터 즉, 메타데이터가 전송된다.
- 소비자가 SQS Extended Client 라이브러리를 사용해 폴링하는 시점에
- 메타데이터를 읽고 S3 로 이동해 S3 에서 데이터를 읽게 된다.
- 흔히 비디오 파일을 처리할 때 사용된다.
SQS - Must Know API
- CraeteQueue (MessageRetentionPeriod): 대기열 큐 생성을 위해 사용되며, 메시지가 폐기되기 전까지
얼마 동안 대기열에 보관될지도 같이 보내야 한다. - DeleteQueue: 대기열 삭제를 위해 사용된다. 대기열 내의 모든 메시지도 삭제된다.
- PurgeQueue: 큐 안의 모든 메시지를 삭제한다.
- SendMessage (DelaySeconds): 메시지를 보낼 때 사용된다. 지연 발송을 위한 인자도 있다.
- ReceiveMessage: 메시지를 폴링하기 위해 사용한다.
- DeleteMessage: 메시지 하나를 삭제한다.
- MaxNumberOfMessages: 기본 값은 1, 최댓값은 10이다. 한 번에 받는 메시지의 양을 의미한다.
ReceiveMessage API를 위한 API다 - ReceiveMessageWaitTimeSeconds: 롱 폴링 대기시간을 정하는 API다.
- ChangeMessageVisibility: 메시지를 처리할 시간이 더 필요할 경우 Visibility timeout을 늘리기위해 사용한다
- SendMessage, DeleteMessage, ChangeMessageVisibility는 묶을으로 사용하여,
API 호출 횟수를 줄여 코스트를 줄여줄 수 있다.
SQS - FIFO Queue
- 선입선출 큐다.
- 선입선출이 가능하도록 내부에서 정렬이 일어난다.
- 표준 대기열보다 더 확실히 순서가 보장된다.
- 순서가 보장되어야 하기 때문에, 제한된 처리량을 가진다.
- 배치 처리가 아닌 경우 초당 300개의 메시지를 처리하고
- 배치로 처리할 경우 초당 3000개를 처리한다.
- 중복을 제거하도록 해주는 기능이 있어 오직 한 번만 보내도 된다.
- 순서를 유지할 필요가 있을 때 FIFO를 사용하도록 하자.
SQS FIFO - Deduplication
- 중복을 제거하는 기능이다.
- 중복제거가 적용되는 간격은 5분이다.
- 즉, 5분 이내에 동일한 메시지를 두 번 발송할 경우 두 번째 메시지는 거부된다.
- 두 가지 방법으로 중복을 제거할 수 있다.
- 내용 기반 중복제거: SQS에 메시지를 보내면 Sha-256 방식으로 해시가 계산된다.
동일한 해시를 가진 경우 제거한다. - Deduplication ID 사용: 직접적으로 ID를 명시해서 중복되는 id가 온다면 삭제한다.
- 내용 기반 중복제거: SQS에 메시지를 보내면 Sha-256 방식으로 해시가 계산된다.
SQS FIFO - Message Grouping
- 큐로 메시지를 보낼 때 MessageGroupID를 동일한 값으로 정할 경우,
해당 ID를 갖고 있는 메시지들은 오직 동일한 사용자에게만 전달된다.- 그리고 그 한 명의 소비자를 위해 모든 메시지들이 순서대로 정렬된다.
- 부분 집합 별로 정렬하고 싶다면 그룹 아이디를 다르게 설정하면 되는 것이다.
- 중요한건 같은 그룹 아이디를 가진 놈들은 내부에서 순서대로 정렬된다.
- 그리고 그 한 명의 소비자를 위해 모든 메시지들이 순서대로 정렬된다.