Блог Amazon Web Services

Построение отказоустойчивых бессерверных паттернов путём комбинации сервисов сообщений

Оригинал статьи: ссылка (James Beswick,  Senior Developer Advocate, AWS Serverless Team) часть 1, часть 2 (текущая), часть 3

В блоге “Выбор сервисов сообщений для бессерверных приложений” я рассказал о функционале и отличиях между основными сервисами сообщений в AWS. Amazon SQSAmazon SNS и Amazon EventBridge предоставляют функционал очередей, модели «издатель-подписчик» и шины сообщений для ваших приложений. По отдельности каждый из этих сервисов – надёжный и масштабируемый, что делает их ключевыми сервисами для построения бессерверных архитектур.

Однако вы также можете комбинировать эти сервисы для решения некоторых проблем в распределённых архитектурах. Используя специфичный функционал каждого сервиса, можно создавать довольно продвинутые архитектурные паттерны при минимальном объёме кода. Такие комбинации могут сделать ваши приложения более отказоустойчивыми, масштабируемыми и помогут снизить объём дополнительной логики и архитектурной сложности в ваших рабочих нагрузках.

В этом посте я расскажу о некоторых важных паттернах для разработчиков бессерверных приложений и покажу, как можно развернуть такие сервисные интеграции с помощью AWS Serverless Application Model (AWS SAM).

Примеры кода, используемые в данной статье, вы сможете найти и загрузить из репозитория GitHub. Файл README.md содержит инструкции по запуску и развёртыванию каждого из примеров кода.

SNS вместе с SQS: добавление отказоустойчивости и регулирование пропускной способности сообщений

SNS предоставляет надёжную политику повторной отправки сообщений, которая позволяет осуществить до 100 010 попыток отправки на протяжении 23 дней. Если конечный адресат недоступен, он может быть перегружен повторениями, когда снова заработает. Вы можете решить данную проблему добавлением очереди SQS.

Добавление очереди SQS между SNS-топиком и подписчиком имеет следующие преимущества. Во-первых, это добавляет отказоустойчивости при доставке сообщения, так как оно гарантированно сохраняется в очереди. Во-вторых, это ограничивает количество сообщений, отправляемых подписчику, помогая сгладить всплески трафика, вызванные попыткой сервиса до-отправить пропущенные сообщения.

Чтобы реализовать такой подход с помощью шаблона AWS SAM, нужно определить два ресурса и SNS-подписку:

  MySqsQueue:
    Type: AWS::SQS::Queue

  MySnsTopic:
    Type: AWS::SNS::Topic
    Properties:
      Subscription:
        - Protocol: sqs
          Endpoint: !GetAtt MySqsQueue.Arn

И, наконец, предоставить права доступа SNS-топику на публикацию сообщений в очередь с помощью ресурса AWS::SQS::QueuePolicy:

  SnsToSqsPolicy:
    Type: AWS::SQS::QueuePolicy
    Properties:
      PolicyDocument:
        Version: "2012-10-17"
        Statement:
          - Sid: "Allow SNS publish to SQS"
            Effect: Allow
            Principal: "*"
            Resource: !GetAtt MySqsQueue.Arn
            Action: SQS:SendMessage
            Condition:
              ArnEquals:
                aws:SourceArn: !Ref MySnsTopic
      Queues:
        - Ref: MySqsQueue

Чтобы протестировать получившееся решение, можно отправить сообщение в SNS-топик и проверить длину очереди SQS с помощью AWS CLI:

aws sns publish --topic-arn "arn:aws:sns:us-east-1:123456789012:sns-sqs-MySnsTopic-ABC123ABC" --message "Test message"
aws sqs get-queue-attributes --queue-url "https://sqs.us-east-1.amazonaws.com/123456789012/sns-sqs-MySqsQueue- ABC123ABC " --attribute-names ApproximateNumberOfMessages

Вы должны получить результат, подобный представленному ниже:

Другой вариант использования данного паттерна – это фильтрация сообщений в очереди SQS. Расположив SNS-топик перед очередью, вы можете использовать функционал фильтрации сообщений сервиса SNS. Это гарантирует, что только нужные вам сообщения попадут в очередь. Для использования фильтрации сообщений в AWS SAM используйте ресурс AWS:SNS:Subcription:

  QueueSubcription:
    Type: 'AWS::SNS::Subscription'
    Properties:
      TopicArn: !Ref MySnsTopic
      Endpoint: !GetAtt MySqsQueue.Arn
      Protocol: sqs
      FilterPolicy:
        type:
        - orders
        - payments 
      RawMessageDelivery: 'true'

EventBridge вместе с SNS: комбинация функционала обоих сервисов

Оба сервиса, SNS и EventBridge, имеют разный набор поддерживаемых адресатов и интеграций. Таблица сравнивает основные различия между двумя сервисами:

Amazon SNS Amazon EventBridge
Количество адресатов 10 млн (можно изменить) 5
Ограничения

100 тыс. топиков.

12,5 млн подписок на топик.

100 шин сообщений.

300 правил на шину сообщений.

Преобразование входящих сообщений Нет Да – см. детали.
Фильтрация сообщений Да – см. детали. Да, включая IP адреса – см. детали.
Поддерживаемые форматы Raw или JSON JSON
Получение сообщений из AWS CloudTrail Нет Да
Адресаты HTTP(S), SMS, SNS Mobile Push, Email/Email-JSON, SQS, Lambda-функции 15 адресатов, включая: AWS LambdaAmazon SQSAmazon SNSAWS Step FunctionsAmazon Kinesis Data StreamsAmazon Kinesis Data Firehose.
Интеграция с SaaS-провайдерами Нет Да – см. список партнёров.
Интеграция c Schema Registry Нет Да – см. детали.
Поддержка Dead-letter очередей Да Нет
Публичная доступность Можно создавать публичные топики Нет
Межрегиональное взаимодействие Функция AWS Lambda может подписаться на SNS-топик в любом регионе. Адресаты должны быть в одном регионе. Можно отправлять сообщения между регионами в другие шины сообщений.

В этом паттерне вы настраиваете SNS-топик в качестве адресата для правила EventBridge:

В шаблоне AWS SAM вы определяете указанные выше ресурсы следующим образом:

Resources:
  MySnsTopic:
    Type: AWS::SNS::Topic

  EventRule: 
    Type: AWS::Events::Rule
    Properties: 
      Description: "EventRule"
      EventPattern: 
        account: 
          - !Sub '${AWS::AccountId}'
        source:
          - "demo.cli"
      Targets: 
        - Arn: !Ref MySnsTopic
          Id: "SNStopic"

EventBridge-шина «по умолчанию» уже существует в каждом аккаунте AWS, поэтому её определять не нужно. Для публикации событий, соответствующих заданным правилам, из EventBridge в SNS-топик нужно определить права доступа, используя ресурс AWS::SNS::TopicPolicy:

  EventBridgeToToSnsPolicy:
    Type: AWS::SNS::TopicPolicy
    Properties: 
      PolicyDocument:
        Statement:
        - Effect: Allow
          Principal:
            Service: events.amazonaws.com
          Action: sns:Publish
          Resource: !Ref MySnsTopic
      Topics: 
        - !Ref MySnsTopic      

EventBridge имеет ограничение на пять адресатов на правило. В случаях, когда необходимо отправить сообщение сотням или тысячам адресатов, публикация сообщений в SNS топик и затем подписка адресатов на этот топик помогает обойти указанное ограничение EventBridge. Оба сервиса поддерживают разных адресатов, и данный паттерн помогает доставлять сообщения из EventBridge на следующие каналы: SMS, HTTP(s), email и мобильные уведомления SNS.

Можно преобразовывать и фильтровать сообщения, используя эти сервисы, часто даже без необоходимости использования функций AWS Lambda. SNS не поддерживает преобразование входящих сообщений, но вы можете это сделать в правиле EventBridge. Фильтрация сообщений поддерживается обоими сервисами, но EventBridge предоставляет больше возможностей.

AWS CloudTrail может логировать и мониторить события, происходящие в сервисах AWS. Он может быть полезным источником событий, позволяя реагировать, например, на изменения объектов в Amazon S3 или изменения в вашей среде разработки. Такой подход натурально интегрируется с EventBridge, позволяя доставлять сообщения от десятков сервисов.

EventBridge также позволяет интегрироваться с источниками событий за пределами вашего аккаунта AWS, предлагая интеграции с SaaS-провайдерами, такими как ZendeskPagerDuty и Auth0. Сообщения доставляются в партнёрскую шину сообщений в вашем аккаунте и затем могут быть отфильтрованы и направлены в SNS-топик для обработки.

Помимо этого, данный паттерн позволяет доставлять сообщения в Lambda-функции в других аккаунтах AWS и в другие регионы. Вы можете запускать Lambda на базе сообщений из SNS-топиков в других регионах и аккаунтах AWS. Вы также можете сделать SNS-топик публичным и открытым только на чтение, предоставляя точку интеграции и расширения для сторонних провайдеров и подписчиков. SNS предоставляет расширенные возможности контроля доступа, которые вы можете интегрировать в данный паттерн.

EventBridge вместе с SQS: построение отказоустойчивых микросервисов

EventBridge может перенаправлять сообщения различным адресатам, включая микросервисы. В случае каскадных ошибок в пайплайне обработки сервис будет повторять отправку сообщений на протяжении 24 часов. Для приложений, требующих более долгий период хранения, можно отправлять сообщения в SQS-очередь, созданную для каждого из микросервисов. Это позволит гарантированно сохранить сообщения до момента полного восстановления микросервиса, подписанного на данную очередь. В дополнение, данный паттерн защищает микросервисы от всплесков трафика путём ограничения количества обрабатываемых за раз сообщений.

Ресурсы в шаблоне AWS SAM похожи на предыдущие примеры, но используют ресурс AWS::SQS::QueuePolicy для предоставления прав доступа к EventBridge:

  EventBridgeToToSqsPolicy:
    Type: AWS::SQS::QueuePolicy
    Properties:
      PolicyDocument:
        Statement:
        - Effect: Allow
          Principal:
            Service: events.amazonaws.com
          Action: SQS:SendMessage
          Resource:  !GetAtt MySqsQueue.Arn
      Queues:
        - Ref: MySqsQueue

Выводы

Вы можете комбинировать сервисы сообщений в ваших архитектурах для реализации сложных паттернов, минимизируя затраты на написание дополнительного кода. Данный пост показывает три примера, демонстрирующих подходы для ограничения всплесков трафика и сохранения сообщений в очереди для последующей обработки, интеграции SNS и EventBridge, а также построения отказоустойчивых микросервисных архитектур.

Чтобы узнать больше о разделённых (decoupled) архитектурах, смотрите серию обучающих матералов по EventBridge. Чтобы ознакомиться с обучающими материалами по бессерверным технологиям, смотрите https://serverlessland.com.