AWS

[AWS] aws 강의 섹션 19 - 1 (SQS - Standard Queue, FIFO Queue, queue Access Policy, DLQ, Visibility Timeout)

대기업 가고 싶은 공돌이 2024. 10. 14. 01:00

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 대기열이어서 메시지 처리를 해야하나,
      적어도 그동안 문제를 파악할 시간이 생긴다.
  • 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분 이내에 동일한 메시지를 두 번 발송할 경우 두 번째 메시지는 거부된다.
  • 두 가지 방법으로 중복을 제거할 수 있다.
    1. 내용 기반 중복제거: SQS에 메시지를 보내면 Sha-256 방식으로 해시가 계산된다.
      동일한 해시를 가진 경우 제거한다.
    2. Deduplication ID 사용: 직접적으로 ID를 명시해서 중복되는 id가 온다면 삭제한다.

SQS FIFO - Message Grouping

  • 큐로 메시지를 보낼 때 MessageGroupID를 동일한 값으로 정할 경우,
    해당 ID를 갖고 있는 메시지들은 오직 동일한 사용자에게만 전달된다.
    • 그리고 그 한 명의 소비자를 위해 모든 메시지들이 순서대로 정렬된다.
      • 부분 집합 별로 정렬하고 싶다면 그룹 아이디를 다르게 설정하면 되는 것이다. 
      • 중요한건 같은 그룹 아이디를 가진 놈들은 내부에서 순서대로 정렬된다.