SNS와 SQS로 알림 팬아웃

AWSBeginner
지금 연습하기

소개

주문 이행에는 모든 주문 알림이 필요하지만 분석에는 새 주문만 필요합니다. 한 번 게시하여 두 대기열로 전달하고 전달 권한을 설정하며 분석 알림을 필터링합니다.

SQS로 작업 전송 및 소비와 리소스 정책으로 버킷 보호하기를 먼저 완료하세요. 이 독립적인 VM에는 설정된 CLI와 관련 없는 참조 데이터가 제공됩니다. 대기열은 알림 대상이며 이 단원에는 Lambda 소비자가 필요하지 않습니다.

인증 시험 관련 주제

이 실습은 다음 시험 주제에 대한 실습 경험을 제공합니다.

주제 만들기 및 대기열 전달 권한 부여

이 단계에서는 주제와 빈 대기열 두 개를 만들고 해당 주제만 전달할 수 있도록 권한을 부여합니다.

**Amazon Simple Notification Service (SNS)**는 주제 구독을 통해 한 번의 게시를 배포합니다. Terminal 옆에서 AWS View를 사용하여 주제 연결, 대기열 본문과 필터를 비교하세요. 참조 데이터를 유지하세요.

cd /home/labex/project

생산자의 SNS 주제를 만드세요. 명령 치환 $(...)는 반환된 ARN을 이후 명령에서 사용할 셸 변수에 저장합니다.

TOPIC_ARN=$(aws sns create-topic --name labex-q04-orders --query TopicArn --output text)

독립적인 대상을 만들고 대기열 URL을 저장하세요.

FULFILLMENT_URL=$(aws sqs create-queue --queue-name labex-q04-fulfillment --query QueueUrl --output text)
ANALYTICS_URL=$(aws sqs create-queue --queue-name labex-q04-analytics --query QueueUrl --output text)

구독은 대기열 ARN을 대상으로 사용합니다. 두 식별자를 선택하세요.

FULFILLMENT_ARN=$(aws sqs get-queue-attributes --queue-url "$FULFILLMENT_URL" --attribute-names QueueArn --query Attributes.QueueArn --output text)
ANALYTICS_ARN=$(aws sqs get-queue-attributes --queue-url "$ANALYTICS_URL" --attribute-names QueueArn --query Attributes.QueueArn --output text)

대기열 정책은 SNS 서비스에 정확히 이 대기열의 sqs:SendMessage를 허용하고 aws:SourceArn을 본인의 주제로 제한합니다. 구독 설정만으로 전달 권한이 부여되지는 않습니다. 대기열마다 일반 JSON 정책을 하나씩 작성하세요. 셸이 ARN 변수를 넣습니다.

cat > fulfillment-policy.json <<EOF
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {"Service": "sns.amazonaws.com"},
    "Action": "sqs:SendMessage",
    "Resource": "$FULFILLMENT_ARN",
    "Condition": {"ArnEquals": {"aws:SourceArn": "$TOPIC_ARN"}}
  }]
}
EOF
cat > analytics-policy.json <<EOF
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {"Service": "sns.amazonaws.com"},
    "Action": "sqs:SendMessage",
    "Resource": "$ANALYTICS_ARN",
    "Condition": {"ArnEquals": {"aws:SourceArn": "$TOPIC_ARN"}}
  }]
}
EOF

SQS의 Policy 속성은 JSON 문자열을 담습니다. --rawfile은 정책 파일을 해당 문자열로 읽으며 이후 CLI가 일반 속성 파일을 적용합니다.

jq -n --rawfile policy fulfillment-policy.json '{Policy:$policy}' > fulfillment-attributes.json
jq -n --rawfile policy analytics-policy.json '{Policy:$policy}' > analytics-attributes.json
aws sqs set-queue-attributes --queue-url "$FULFILLMENT_URL" --attributes file://fulfillment-attributes.json
aws sqs set-queue-attributes --queue-url "$ANALYTICS_URL" --attributes file://analytics-attributes.json

설정된 권한을 읽으세요.

aws sqs get-queue-attributes --queue-url "$FULFILLMENT_URL" --attribute-names QueueArn Policy
aws sqs get-queue-attributes --queue-url "$ANALYTICS_URL" --attribute-names QueueArn Policy

두 정책은 각각 자체 대기열과 동일한 주문 주제를 지정합니다. AWS View에는 주제 하나와 빈 대기열 두 개가 표시되며 아직 구독은 없습니다.

두 대기열 구독 및 분석 필터링

이 단계에서는 각 대기열을 주제에 연결하고 분석이 받을 알림을 선택합니다.

SNS 팬아웃과 구독 필터

분석 구독은 메시지 속성 kind=created를 선택하며 각 대기열은 자체 복사본을 받습니다.

구독은 프로토콜과 엔드포인트를 SNS 주제에 연결합니다. sqs의 엔드포인트는 대기열 ARN입니다. 각 연결을 설정하고 나중에 제거할 수 있도록 구독 ARN을 저장하세요.

FULFILLMENT_SUB=$(aws sns subscribe --topic-arn "$TOPIC_ARN" --protocol sqs --notification-endpoint "$FULFILLMENT_ARN" --query SubscriptionArn --output text)
ANALYTICS_SUB=$(aws sns subscribe --topic-arn "$TOPIC_ARN" --protocol sqs --notification-endpoint "$ANALYTICS_ARN" --query SubscriptionArn --output text)

필터 정책은 구독 하나에 전달할 알림을 선택합니다. 기본 필터 범위는 메시지 속성입니다. 분석은 값이 created인 String 속성 kind만 받습니다. 주문 이행에는 필터가 없습니다.

aws sns set-subscription-attributes --subscription-arn "$ANALYTICS_SUB" --attribute-name FilterPolicy --attribute-value '{"kind":["created"]}'

두 구독과 분석 속성을 확인하세요.

aws sns list-subscriptions-by-topic --topic-arn "$TOPIC_ARN"
aws sns get-subscription-attributes --subscription-arn "$ANALYTICS_SUB"

SQS 엔드포인트 두 개와 분석 필터가 나와야 합니다. 원시 메시지 전달은 기본적으로 꺼져 있으므로 대기열 본문에는 주제, 메시지 ID, 원래 메시지 문자열과 속성을 포함하는 SNS 알림 봉투가 들어갑니다. 게시하기 전까지 대기열은 비어 있습니다.

팬아웃, 필터링과 전달 경계 증명

이 단계에서는 알림 두 개를 게시하고 실제 독립적인 전달을 확인합니다.

created 이벤트를 게시하세요. JSON 메시지는 비즈니스 페이로드입니다. 별도의 String 속성이 이 구독 필터의 평가 대상입니다.

aws sns publish --topic-arn "$TOPIC_ARN" --message '{"id":"fanout-order","kind":"created"}' --message-attributes '{"kind":{"DataType":"String","StringValue":"created"}}'

같은 주문 ID로 updated 이벤트를 게시하세요.

aws sns publish --topic-arn "$TOPIC_ARN" --message '{"id":"fanout-order","kind":"updated"}' --message-attributes '{"kind":{"DataType":"String","StringValue":"updated"}}'

AWS View를 관찰하세요. 주문 이행에는 알림 두 개가 있고 분석에는 created 알림만 있습니다. 개수를 확인하세요.

aws sqs get-queue-attributes --queue-url "$FULFILLMENT_URL" --attribute-names ApproximateNumberOfMessages ApproximateNumberOfMessagesNotVisible
aws sqs get-queue-attributes --queue-url "$ANALYTICS_URL" --attribute-names ApproximateNumberOfMessages ApproximateNumberOfMessagesNotVisible

확인을 위해 표시 제한 시간을 0으로 하여 수신하세요. 테스트 메시지를 처리 중 상태로 유지하지 않고 즉시 해제하여 나중에 정리할 수 있도록 합니다. 이 예시는 처리나 확인 처리가 아닌 독립적인 복사본을 증명합니다. fromjson은 각 봉투 문자열을 읽으며 마지막 필드 선택은 여기서 사용하는 알림 필드를 보여 줍니다.

aws sqs receive-message \
  --queue-url "$FULFILLMENT_URL" \
  --max-number-of-messages 10 \
  --visibility-timeout 0 \
  --output json | jq '[.Messages[].Body | fromjson | {Type, TopicArn, MessageId, Message, MessageAttributes}]'
aws sqs receive-message \
  --queue-url "$ANALYTICS_URL" \
  --max-number-of-messages 10 \
  --visibility-timeout 0 \
  --output json | jq '[.Messages[].Body | fromjson | {Type, TopicArn, MessageId, Message, MessageAttributes}]'

본문은 SNS 봉투입니다. Type은 Notification, TopicArn은 본인의 주제이며 Message에는 원래 JSON 문자열이 들어 있습니다. 두 대기열의 created 알림은 같은 SNS MessageId를 갖습니다. 각 대기열은 자체 SQS 메시지를 보관합니다. 주문 이행은 분석에서 필터링된 updated 이벤트도 보관합니다. 독립적인 소비자는 복사본을 따로 확인 처리할 수 있습니다.

이제 주제 권한이 중요한 이유를 테스트하세요. 주문 이행의 aws:SourceArn을 일시적으로 관련 없는 테스트 주제 ARN으로 설정하세요.

jq --arg wrong 'arn:aws:sns:us-east-1:123456789012:labex-q04-unrelated' '.Statement[0].Condition.ArnEquals["aws:SourceArn"]=$wrong' fulfillment-policy.json > wrong-source-policy.json
jq -n --rawfile policy wrong-source-policy.json '{Policy:$policy}' > wrong-source-attributes.json
aws sqs set-queue-attributes --queue-url "$FULFILLMENT_URL" --attributes file://wrong-source-attributes.json

다른 테스트 주문의 updated 알림을 게시하세요. SNS는 게시를 접수하지만 주문 이행에는 더 이상 이 주제에 대한 권한이 없습니다. 분석은 updated 속성을 필터링합니다.

aws sns publish --topic-arn "$TOPIC_ARN" --message '{"id":"blocked-order","kind":"updated"}' --message-attributes '{"kind":{"DataType":"String","StringValue":"updated"}}'

대기열 개수가 2와 1로 유지되고 AWS View에 blocked-order 봉투가 없는지 확인하세요.

aws sqs get-queue-attributes --queue-url "$FULFILLMENT_URL" --attribute-names ApproximateNumberOfMessages
aws sqs get-queue-attributes --queue-url "$ANALYTICS_URL" --attribute-names ApproximateNumberOfMessages

성공한 게시 응답은 SNS가 알림을 접수했음을 증명합니다. 대상 전달에는 자체 증거가 필요합니다. 단계 검사 전에 정확한 원래 정책을 복구하세요.

aws sqs set-queue-attributes --queue-url "$FULFILLMENT_URL" --attributes file://fulfillment-attributes.json

이 작업 공간은 같은 계정 내 즉시 대기열 전달과 String 속성 필터를 테스트합니다. 프로덕션 SNS 필터 변경은 전파에 최대 15분이 걸릴 수 있으며 실패한 전달에는 서비스 재시도 동작이 있습니다. 이 짧은 권한 실험은 프로덕션 재시도 모델이 아닙니다.

주문 이행에는 created와 updated 알림이 있고 분석에는 같은 SNS 메시지 ID의 created 알림만 있는 AWS View 예시

연결과 일회용 알림 제거

이 단계에서는 관련 없는 참조 데이터를 유지하면서 두 구독, 주제와 대기열을 제거합니다.

두 엔드포인트의 구독을 먼저 취소하세요.

aws sns unsubscribe --subscription-arn "$FULFILLMENT_SUB"
aws sns unsubscribe --subscription-arn "$ANALYTICS_SUB"

주제와 대기열을 삭제하세요. 대기열 삭제는 테스트 알림을 버립니다. 이 알림들이 비즈니스 처리를 완료했다고 주장하지는 않았습니다.

aws sns delete-topic --topic-arn "$TOPIC_ARN"
aws sqs delete-queue --queue-url "$FULFILLMENT_URL"
aws sqs delete-queue --queue-url "$ANALYTICS_URL"

성공한 네이티브 쿼리로 정리를 증명하세요.

aws sns list-topics
aws sns list-subscriptions
aws sqs list-queues
aws dynamodb scan --table-name labex-q04-reference --query Items

주제와 구독 목록은 비어 있고 대기열 URL은 없으며 참조 항목에는 여전히 keep unchanged가 있습니다. 인증 실패나 네트워크 실패는 삭제를 증명하지 않습니다. AWS View는 같은 빈 리소스 상태를 보여 줍니다.

일반 설정 파일을 제거하세요.

rm -f fulfillment-policy.json analytics-policy.json fulfillment-attributes.json analytics-attributes.json wrong-source-policy.json wrong-source-attributes.json

환경을 종료하기 전에 정리 검사를 실행하세요.

요약

SNS 주제 하나를 독립적인 SQS 대기열 두 개에 연결하고 전달을 정확한 주제 소스로 제한했으며 메시지 속성으로 분석을 필터링했습니다. 실제 알림 봉투는 공유된 게시 이벤트와 별도의 대기열 복사본을 증명했습니다. 또한 SNS의 게시 접수와 대상에 도달하는 전달을 구별한 다음 참조 데이터를 유지하면서 본인의 리소스를 제거했습니다.

대기열 소비자는 여전히 반복 전달을 처리해야 합니다. 다음 단원은 반복되는 작업이 중복 비즈니스 효과를 만들지 않도록 원자적인 DynamoDB 조건을 적용합니다.