Distribua Notificações com SNS e SQS

AWSBeginner
Pratique Agora

Introdução

A equipe de atendimento de pedidos precisa de todas as notificações, enquanto a equipe de análise precisa apenas de novos pedidos. Você publicará uma vez para duas filas, configurará suas permissões de entrega e filtrará as notificações de análise.

Conclua primeiro Envie e Consuma Tarefas com SQS e Proteja um bucket com uma política de recurso. Esta VM independente fornece uma CLI configurada e dados de referência não relacionados. As filas são destinos de notificações; esta unidade não precisa de um consumidor Lambda.

Relação com as certificações

Este laboratório oferece prática nos seguintes tópicos de exame.

Crie o Tópico e Autorize a Entrega às Filas

Nesta etapa, crie um tópico e duas filas vazias com permissão de entrega apenas para esse tópico.

O Amazon Simple Notification Service (SNS) distribui uma publicação por meio das assinaturas de um tópico. Use AWS View ao lado do Terminal para comparar conexões do tópico, corpos das mensagens nas filas e filtros; preserve os dados de referência.

cd /home/labex/project

Crie o tópico SNS do produtor. A substituição de comando, $(...), salva o ARN retornado em uma variável do shell para os comandos seguintes:

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

Crie destinos independentes e salve suas URLs de fila:

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)

As assinaturas usam ARNs de filas como destinos. Selecione os dois identificadores:

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)

Uma política de fila concede ao serviço SNS sqs:SendMessage nesta fila exata, com aws:SourceArn limitado ao seu tópico. A configuração da assinatura, por si só, não concede permissão de entrega. Escreva uma política JSON comum por fila; o shell insere as variáveis de 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

O atributo Policy do SQS contém uma string JSON. --rawfile lê um arquivo de política nessa string e, depois, a CLI aplica o arquivo comum de atributos:

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

Leia as permissões configuradas:

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

As duas políticas indicam sua própria fila e o mesmo tópico de pedidos. AWS View mostra um tópico, duas filas vazias e ainda nenhuma assinatura.

Inscreva as Duas Filas e Filtre as Notificações de Análise

Nesta etapa, conecte cada fila ao tópico e escolha quais notificações a análise recebe.

Distribuição SNS e filtro de assinatura

A assinatura de análise seleciona o atributo de mensagem kind=created; cada fila recebe sua própria cópia.

Uma assinatura conecta um protocolo e um endpoint a um tópico SNS. Para sqs, o endpoint é o ARN da fila. Salve os ARNs das assinaturas para configurar e, depois, remover cada conexão:

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)

Uma política de filtro seleciona notificações para uma assinatura. O escopo padrão do filtro são os atributos de mensagem. A análise aceita apenas um atributo String kind com valor created; o atendimento de pedidos não tem filtro:

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

Inspecione as duas assinaturas e os atributos da assinatura de análise:

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

Espere dois endpoints SQS e o filtro de análise. A entrega de mensagens brutas está desativada por padrão, portanto os corpos nas filas conterão um envelope de notificação SNS com o tópico, o ID da mensagem, a string da mensagem original e os atributos. As filas permanecem vazias até a publicação.

Comprove a Distribuição, a Filtragem e o Limite de Entrega

Nesta etapa, publique duas notificações e inspecione entregas reais independentes.

Publique um evento de criação. A mensagem JSON é o conteúdo de negócio; o atributo String separado é o que o filtro desta assinatura avalia:

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

Publique um evento de atualização com o mesmo ID de pedido:

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

Observe AWS View: o atendimento de pedidos tem duas notificações, e a análise tem apenas a notificação de criação. Verifique as contagens:

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

Receba para inspeção com visibilidade zero. Isso libera imediatamente essas mensagens sintéticas para a limpeza posterior, em vez de mantê-las em processamento. O exemplo comprova cópias independentes, não processamento ou confirmação. fromjson lê cada string de envelope, e a seleção final de campos mostra os campos de notificação usados aqui:

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}]'

O corpo é um envelope SNS: Type é Notification, TopicArn é seu tópico e Message contém a string JSON original. A notificação de criação tem o mesmo MessageId SNS nas duas filas; cada fila mantém sua própria mensagem SQS. O atendimento de pedidos também mantém o evento de atualização, que a análise excluiu pelo filtro. Consumidores independentes podem confirmar suas cópias separadamente.

Agora teste por que a permissão do tópico importa. Defina temporariamente o aws:SourceArn do atendimento de pedidos como um ARN sintético de tópico não relacionado:

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

Publique uma notificação de atualização para outro pedido sintético. O SNS aceita a publicação, mas o atendimento de pedidos já não está autorizado para este tópico; a análise filtra o atributo de atualização:

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

Verifique que as contagens das filas continuam em dois e um, sem envelope blocked-order em AWS View:

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

Uma resposta de publicação bem-sucedida comprova que o SNS aceitou a notificação; a entrega ao destino precisa de sua própria evidência. Restaure a política original exata antes da verificação da etapa:

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

Este ambiente de trabalho testa a entrega imediata a filas na mesma conta e filtros de atributos String. Alterações de filtros SNS em produção podem levar até 15 minutos para se propagar, e entregas com falha têm o comportamento de novas tentativas do serviço; este breve experimento de permissão não é um modelo de novas tentativas em produção.

Exemplo de AWS View: o atendimento de pedidos mantém notificações de criação e atualização; a análise mantém apenas a notificação de criação com o mesmo ID de mensagem SNS.

Remova as Conexões e as Notificações Descartáveis

Nesta etapa, remova as duas assinaturas, o tópico e as filas, preservando os dados de referência não relacionados.

Cancele primeiro a assinatura dos dois endpoints:

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

Exclua o tópico e as filas. A exclusão das filas descarta as notificações sintéticas; nenhum processamento de negócio foi alegado para elas:

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

Comprove a limpeza usando consultas nativas bem-sucedidas:

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

As listas de tópicos e assinaturas estão vazias, as URLs de fila estão ausentes e o item de referência ainda diz keep unchanged. Falhas de autenticação ou de rede não comprovam a exclusão. AWS View mostra os mesmos recursos vazios.

Remova seus arquivos comuns de configuração:

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

Execute a verificação da limpeza antes de encerrar o ambiente.

Resumo

Você conectou um tópico SNS a duas filas SQS independentes, limitou a entrega a um tópico de origem exato e filtrou a análise usando um atributo de mensagem. Envelopes reais de notificação comprovaram o evento publicado compartilhado e as cópias separadas nas filas. Você também distinguiu a aceitação de uma publicação pelo SNS da entrega aos destinos e, depois, removeu seus recursos, preservando os dados de referência.

Consumidores de filas ainda precisam lidar com entregas repetidas. A próxima unidade aplica uma condição atômica do DynamoDB para impedir que tarefas repetidas produzam efeitos de negócio duplicados.