관리 메뉴

CS

AWS SQS 써보기: 다른 서비스에 정보를 전달(메시지 큐) 본문

AWS

AWS SQS 써보기: 다른 서비스에 정보를 전달(메시지 큐)

vcxz 2023. 6. 2. 18:28

 

AWS SQS는 AWS 메시지 큐 서비스 중 하나입니다.

 

메시지 큐는 보통 아키텍처의 규모가 어느 정도 큰 경우 사용하는 서비스로, 이를 사용하면 큐 방식으로 어떤 서비스에서 다른 서비스로 정보(메시지)를 보낼 수 있습니다. 일단 비동기 장점이 있고, 서비스끼리 직접 통신할 경우 연결 과정 자체도 번거롭고 해당 서비스를 변경하기가 어려워지기 때문입니다. 또한 모든 메시지를 메시지 큐에 모은 후, 서비들이 자기가 원하는 정보만 가져가도록 만들 수 있기 때문에(이를 '구독'이라 함) 구성하기가 편한 점도 있습니다. 참고로 메시지 큐처럼 애플리케이션 간 통신에 사용되는 소프트웨어를 미들웨어라고 부릅니다.

 

Simple Queue Service라는 이름처럼, 다른 메시지 큐 서비스보다 간단한 듯합니다. 콘솔상에서 금방 만들 수 있고, FIFO 대기열을 쓰면 별다른 작업 없이 선입선출 및 정확히 1회만 처리할 수 있습니다.

 

AWS SQS 문서입니다.

 

 

  1. 대기열 생성
  2. 메시지 전송 및 수신과 삭제
  3. Lambda 트리거

 

 

대기열 생성

콘솔에서 SQS 서비스로 들어가 대기열 생성 버튼을 클릭하여 SQS 대기열을 생성할 수 있습니다.

 

대기열 유형은 '표준'과 'FIFO'가 있습니다. FIFO는 'First In, First Out' 즉 선입선출을 뜻합니다.

표준 대기열은 거의 무제한에 가까운 초당 트랜잭션이 가능하지만, 1회 이상 전송될 수 있으며 순서를 보장하지 않습니다.

FIFO 대기열은 초당 최대 3000개 트랜잭션까지만 가능하지만, 먼저 들어간 게 먼저 나온다는 큐 방식을 제대로 보장하고 딱 1회만 전송됩니다.

저는 FIFO 대기열로 생성하도록 하겠습니다.

 

 

구성 부분 일부 설명입니다.

- 표시(가시성) 제한 시간: 보통 메시지 큐는 여러 서비스를 대상으로 하는데, 한 서비스가 메시지를 수신한 경우 표시 제한 시간 동안은 다른 서비스가 해당 메시지를 수신할 수 없습니다. 표시 제한 시간이 끝났는데도 해당 메시지가 잔존할 경우 다른 서비스도 해당 메시지를 볼 수 있습니다. 이를 방지하려면 표시 제한 시간 내에 해당 메시지를 삭제해야 합니다.

 

- 메시지 보존 기간: 큐에 메시지를 보관하는 기간입니다. 기간이 끝나면 메시지는 삭제됩니다.

 

- 메시지 수신 대기 시간: '폴링(polling)' 시간입니다. 폴링은 SQS의 작동 메커니즘으로, '개표하다'는 단어의 의미처럼 메시지를 뽑는 것을 말합니다. 그냥 메시지를 가져다 주는 게 아니라 받는 서비스가 메시지를 뽑는 것입니다.

메시지 수신 대기 시간을 0초로 하는 것을 짧은 폴링이라고 하는데, 이러면 뽑을 메시지가 없어도 폴링을 해버립니다. 반면 메시지 수신 대기 시간을 두는 것을 긴 폴링이라고 하고 이 경우 메시지가 사용 가능해지거나 시간이 다 되어야 폴링을 합니다. 전송 지연은 애초에 메시지를 늦게 보내는 것이기 때문에 이와 다른 개념입니다.

메시지를 전달하려고 메시지 큐를 쓰는 것이기 때문에 보통 긴 폴링을 쓰되, 반응을 바로바로 얻어야 하는 경우 짧은 폴링을 쓴다고 합니다.

 

FIFO 대기열의 경우 중복을 제거하기 때문에 이에 관한 설정이 더 있습니다.

- 콘텐츠 기반 중복 제거: 기본적으로 메시지 중복을 막기 위해 메시지에 ID를 부여해야 합니다. 콘텐츠 기반 중복 제거를 사용한다면 따로 ID를 부여할 필요 없이 대기열이 알아서 콘텐츠에 기반하여 ID를 부여합니다.

 

 

메시지 전송 및 수신과 삭제

대기열을 생성하였다면 메시지를 보내봅시다.

(python3의 boto3를 사용하겠습니다. boto3의 SQS 문서입니다.)

 

import boto3


# 클라이언트 접속
sqs = boto3.client('sqs',
                   region_name='ap-northeast-2')

# 메시지 전송
response = sqs.send_message(
    QueueUrl='대기열 URL',
    MessageBody='메시지 내용',
    MessageGroupId='메시지 그룹 ID'
)

간단한 메시지 전송 코드입니다.

client.send_message()의 인자

- QueueUrl: 대기열의 URL입니다. 콘솔에서 대기열 세부 정보의 'URL'을 기재하면 됩니다.

- MessageBody: 메시지의 본체입니다. 여기에 메시지를 적으면 됩니다.

- MessageGroupId: FIFO 대기열에서 메시지를 구분하기 위해 필요한 ID입니다. 다른 메시지 그룹 ID와 구분되도록 적절히 정하면 됩니다.

 

여러 개를 보내고 싶으면 코드에서 반복문을 활용하거나, client.send_message_batch()를 사용할 수 있습니다.

MessageBody는 문자열만 되니까, 다른 형식의 데이터를 보내고 싶으면 JSON을 이용하는 게 좋을 것 같습니다.

 

콘솔에서도 메시지를 보낼 수 있고 폴링도 해볼 수 있습니다. 대기열 정보에서 '메시지 전송 및 수신' 버튼을 클릭해 진행하면 됩니다.

 

 

이제 메시지를 수신해 봅시다.

# 메시지 수신
response = sqs.receive_message(
    QueueUrl='대기열 URL'
)

# 메시지 삭제
# 메시지를 수신한 경우
if 'Messages' in response:
    # 각 메시지별
    for message in response['Messages']:
        rsp = sqs.delete_message(
            QueueUrl='대기열 URL',
            ReceiptHandle=message['ReceiptHandle']
        )

client.receive_message()는 최대 10개의 메시지를 수신할 수 있습니다.

 

메시지는 다른 서비스에서도 쓸 게 아니라면 수신 후 삭제하는 게 좋은 것 같습니다.

client.delete_message()로 하나씩 삭제하거나, client.delete_message_batch()로 여러 개를 한 번에 삭제할 수 있습니다. 메시지를 삭제할 때는 ReceiptHandle이 필요합니다. 이는 메시지 수신에 부여된 ID라 할 수 있습니다.

참고로 메시지의 표시 제한 시간 중에도 메시지 삭제는 됩니다.

 

 

Lambda 트리거

또한 SQS는 AWS Lambda를 트리거할 수 있기 때문에 콘솔에서 트리거 설정을 할 수 있습니다. 그러면 대기열에 메시지가 들어가면 Lambda에 event로 입력됩니다. (AWS SQS에서 Lambda 사용 문서)

이때 FIFO 대기열 event의 예시는 다음과 같습니다.

{
    "Records": [
        {
            "messageId": "11d6ee51-4cc7-4302-9e22-7cd8afdaadf5",
            "receiptHandle": "AQEBBX8nesZEXmkhsmZeyIE8iQAMig7qw...",
            "body": "Test message.",
            "attributes": {
                "ApproximateReceiveCount": "1",
                "SentTimestamp": "1573251510774",
                "SequenceNumber": "18849496460467696128",
                "MessageGroupId": "1",
                "SenderId": "AIDAIO23YVJENQZJOL4VO",
                "MessageDeduplicationId": "1",
                "ApproximateFirstReceiveTimestamp": "1573251510774"
            },
            "messageAttributes": {},
            "md5OfBody": "e4e68fb7bd0e697a0ae8f1bb342846b3",
            "eventSource": "aws:sqs",
            "eventSourceARN": "arn:aws:sqs:us-east-2:123456789012:fifo.fifo",
            "awsRegion": "us-east-2"
        }
    ]
}

event['Records']가 각 메시지를 담은 리스트이고,

event['Records'][인덱스]['body']로 각 메시지 내용에 접근할 수 있습니다.