AWSMiddleTechnical

Что такое fan-out pattern SNS → SQS?

Producer публикует событие в SNS topic один раз — SNS доставляет копию в каждую подписанную SQS-очередь. Каждый consumer получает независимый буфер, DLQ и retry policy. Filter policy позволяет очереди получать только релевантные типы событий.

Fan-out SNS → SQS

Fan-out — архитектурный паттерн, при котором одно событие обрабатывается несколькими независимыми системами одновременно. SNS публикует событие один раз, а каждая подписанная SQS-очередь получает свою копию. Это позволяет billing, warehouse и analytics работать независимо: разный темп, своя DLQ, свой visibility timeout.

Настройка через AWS CLI + Python

# 1. Создаём SNS topic
aws sns create-topic --name order-events
# -> TopicArn: arn:aws:sns:eu-west-1:123456789012:order-events

# 2. Создаём SQS очереди для каждого consumer
aws sqs create-queue --queue-name billing-orders
aws sqs create-queue --queue-name warehouse-orders
aws sqs create-queue --queue-name analytics-orders

# 3. Подписываем каждую очередь на topic
aws sns subscribe \
  --topic-arn arn:aws:sns:eu-west-1:123456789012:order-events \
  --protocol sqs \
  --notification-endpoint arn:aws:sqs:eu-west-1:123456789012:billing-orders
import boto3
import json

sns = boto3.client('sns', region_name='eu-west-1')

TOPIC_ARN = 'arn:aws:sns:eu-west-1:123456789012:order-events'

# Producer публикует событие один раз — SNS рассылает в все три очереди
def emit_order_created(order_id: str, customer_id: str, total: float):
    sns.publish(
        TopicArn=TOPIC_ARN,
        Message=json.dumps({
            'order_id': order_id,
            'customer_id': customer_id,
            'total': total,
            'version': '1'
        }),
        MessageAttributes={
            # Filter policy по этому атрибуту позволяет отфильтровать
            # события на стороне SNS до попадания в очередь
            'event_type': {
                'DataType': 'String',
                'StringValue': 'OrderCreated'
            }
        }
    )

Filter policy: подписка только на нужные события

# Применяем filter policy к подписке analytics-orders:
# они хотят только крупные заказы (event_type=OrderCreated)
SUBSCRIPTION_ARN="arn:aws:sns:eu-west-1:123456789012:order-events:subscription-id"

aws sns set-subscription-attributes \
  --subscription-arn $SUBSCRIPTION_ARN \
  --attribute-name FilterPolicy \
  --attribute-value '{"event_type": ["OrderCreated", "OrderUpdated"]}'

SQS Queue Policy — разрешаем SNS писать в очередь

{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {"Service": "sns.amazonaws.com"},
    "Action": "sqs:SendMessage",
    "Resource": "arn:aws:sqs:eu-west-1:123456789012:billing-orders",
    "Condition": {
      "ArnEquals": {
        "aws:SourceArn": "arn:aws:sns:eu-west-1:123456789012:order-events"
      }
    }
  }]
}

Подводные камни

  • Не добавить SQS Queue Policy с разрешением sqs:SendMessage для SNS: delivery молча упадёт, сообщения не дойдут, и это трудно заметить без DLQ или метрик.
  • Не настроить DLQ на каждой очереди: отравленное сообщение будет крутиться до maxReceiveCount, блокируя throughput и маскируя баг в consumer.
  • Игнорировать idempotency: каждая очередь получает копию, но при SNS retry (при недоступности) или re-drive из DLQ consumer может получить дубликат — должен обрабатывать его безопасно.
  • Не версионировать схему события: если producer добавит новое обязательное поле без согласования, все downstream consumers сломаются одновременно.
  • Смешивать Standard и FIFO очереди без понимания: SNS FIFO topic работает только с SQS FIFO queues, а throughput ограничен 300 msg/s (3000 с batching).
  • Не следить за метрикой NumberOfMessagesSent на topic и ApproximateNumberOfMessagesNotVisible на очередях: можно пропустить накопление backlog у одного из consumers.
  • Использовать filter policy с атрибутом типа Number для строковых значений: SNS не приведёт тип автоматически, фильтр не сработает и очередь будет получать всё подряд.
  • Не тестировать cross-account fan-out: если topic и очередь в разных AWS accounts, resource policy нужна с обеих сторон, и это частый источник production-инцидентов при первом деплое.

Common mistakes

  • Подключать всех consumers к одной SQS queue и ожидать fan-out.
  • Не настраивать queue policy для SNS delivery.
  • Забывать DLQ и idempotent processing.

What the interviewer is testing

  • Описывает SNS topic и отдельные SQS queues.
  • Учитывает retries, DLQ и filters.
  • Понимает независимость consumers.

Sources

Related topics