Я обнаружил несколько проблем при реализации веб-перехватчиков на основе шлюза API для наших клиентов, использующих Serverless Framework с пользовательским доменом. Надеемся, что эта статья поможет многим другим людям использовать подобную архитектуру для своих соответствующих вариантов использования.

Недавно я работал над проектом в Zuma по встраиванию веб-перехватчиков в нашу платформу, чтобы наши внешние партнеры могли делиться с нами своими данными. Это помогло нам решить 2 разные проблемы: во-первых, это приблизило нас к полной архитектуре на основе потоковой передачи, где события передаются нам, когда они генерируются почти в реальном времени, а во-вторых, была улучшена обработка ошибок, когда наши внешние партнеры могут запустить и забыть. в то время как мы будем иметь дело с данными и сбоями, связанными с их обработкой, на нашей стороне с повторными попытками, повторными вызовами на основе очереди недоставленных сообщений и т. д. Я ожидаю, что это будет беспроигрышная ситуация как для нас, так и для наших партнеров с точки зрения экономии затрат на эксплуатацию и укрепление доверия к нашим системам.

Чтобы создать эти веб-хуки, я изучил следующие решения:

  1. Добавление веб-перехватчиков в качестве разных конечных точек в наш существующий бэкенд портала. Серверная часть портала — это приложение expressJs, размещенное на AWS Fargate, поддерживаемое балансировщиком нагрузки. Самым большим недостатком будет отсутствие изоляции арендаторов, т. е. пользователи портала и внешние клиенты будут конкурировать за ресурсы в определенные периоды занятости. Создание нового приложения expressJs отдельно для веб-перехватчиков будет излишним с точки зрения операционной нагрузки на команду инженеров.
  2. Добавление веб-перехватчиков в наше приложение Serverless Framework (или просто Serverless), которое обеспечивает нашу интеграцию. Здесь мы извлекаем данные из систем, принадлежащих нашим партнерам, обрабатываем их и передаем нашему ИИ Келси. Поскольку бессерверное приложение — это просто набор AWS Lambda, связанных вместе, каждый из этих веб-перехватчиков будет просто еще одним Lambda. Это было бы идеально, так как Serverless может упростить развертывание, тестирование и эксплуатацию, и мы сохраняем все наши интеграции вместе.

Следующей проблемой было то, как нам раскрыть эти Lambdas? Наши клиенты, как правило, довольны услугами на основе HTTP, поэтому нам были доступны только 2 решения:

  1. Перед Lambdas стоял балансировщик нагрузки, назначая личный домен балансировщику нагрузки с использованием Route53. Балансировщики нагрузки приложений в AWS сопоставляют маршруты с целевыми группами, где целевой группой может быть любой вычисляемый механизм в AWS, такой как EC2, ECS или Lambda, для каждого порта. Самым большим ограничением этого является то, что мы можем иметь только 100 правил в сопоставлениях, для нас это будет только 100 веб-хуков. Кроме того, нашим разработчикам нравилось владеть собственной версией всего бессерверного приложения, что позволяло нам быстро тестировать вещи. Наличие балансировщика нагрузки для каждого разработчика было бы излишним, в то время как совместное использование нашего тестового балансировщика нагрузки приведет к ограничению правила. Другим недостатком этого решения была необходимость настраивать балансировщик нагрузки вне Serverless Framework, поскольку отсутствие всей конфигурации инфраструктуры в одном месте делало это решение непривлекательным.
  2. Другим решением является использование Lambda с помощью шлюза API, а затем назначение пользовательского домена шлюзу API с использованием Route53. Это может быть полностью обеспечено с помощью Serverless Framework, и у каждого разработчика может быть свой собственный стек. Хотя это выглядело очень многообещающе, я столкнулся с несколькими проблемами, чтобы заставить это работать на начальном этапе. Давайте поговорим об этом далее.

Концепции сервисов AWS

1. Маршрут53

Route53 — это то, что позволит нам использовать доменное имя или даже субдомен для нашего веб-перехватчика. Если мы просто используем API Gateway, он предоставляет URL-адрес, который выглядит примерно так: https://ba66fyn12i.execute-api.us-east-1.amazonaws.com, который также может измениться в любое время, поскольку генерируется каждый раз, когда мы вносим изменения в шлюз API. Было бы невозможно или профессионально, даже если бы было возможно, использовать этот URL для нашего варианта использования.

2. Шлюз API

Шлюз API — это бессерверная инфраструктура как услуга, которая позволяет нам создавать службы API, просто определяя маршруты API и их обработчик, скорее всего, Lambda. И все остальное, от балансировки нагрузки до управления соединениями HTTP/веб-сокетов, автоматическое масштабирование поставляется из коробки. Вот несколько важных вещей, которые нам нужно знать для работы с API Gateway:

а. Пользовательские домены

Мы можем связать собственный домен с нашим шлюзом API. В нашем случае мы будем настраивать региональный шлюз API, поскольку шлюз API, оптимизированный для Edge, не работает с шлюзом API версии 2 или HTTP (ограничение шлюза API 1). Поскольку мы хотели бы связать несколько этапов с одним и тем же пользовательским доменом в качестве разных базовых путей для разработки, контроля качества и производства, для которых нам нужно использовать шлюз HTTP API в качестве шлюза API для отдыха (ограничение шлюза API 2).

б. Сопоставления API и базовые пути

Сопоставление API связывает API и его этап с личным доменом. Это то, что позволяет нам использовать различные этапы, такие как разработка, производство и т. д., в своих пользовательских доменах. Мы будем использовать другой способ подключения различных этапов подготовки, таких как этапы разработки и контроля качества, к одному и тому же пользовательскому поддомену с помощью базовых путей, например. https://stage-webhook.‹custom-domain›.com/dev для разработчиков, https://stage-webhook.‹custom-domain› .com/qa для контроля качества, но с тем же этапом разработки шлюза API, а затем используйте другой настраиваемый субдомен для этапа производства, например https://webhook.‹custom-domain. ›.com без базового пути.

в. Интеграции

Каждый путь, определенный в шлюзе API, связан с лямбдой, которая обрабатывает запрос. Эта ассоциация называется «Интеграции», и ее можно увидеть в разделе «Интеграции» в консоли шлюза API.

d. V1/V2

В настоящее время существует 2 типа шлюза API: Rest (V1) и HTTP (V2). Версия HTTP поддерживает только региональные конечные точки, но мы можем связать разные базовые пути, в то время как Rest также поддерживает конечные точки, оптимизированные для Edge. Более новый HTTP также должен снизить стоимость выполнения по сравнению с версией Rest. Если мы можем использовать новую HTTP-версию API Gateway, лучше это сделать.

3. Лямбда

Лямбды — это вычислительные блоки, обрабатывающие запросы, поступающие от шлюза API. Именно здесь развертывается и запускается наша бизнес-логика.

а. Выделенная емкость

Если между обращениями к нашему веб-хуку есть промежутки, микро виртуальные машины Lambda, которые обслужили предыдущий запрос, уничтожаются и перезапускаются. Это приводит к проблемам с холодным запуском, из-за которых задержки превышают несколько секунд. Чтобы решить эту проблему, мы можем сказать Lambda, чтобы определенное количество экземпляров всегда работало. Этот номер предоставляется Lambda как Provisioned Capacity.

б. Зарезервированная мощность

С увеличением количества запросов Lambda будет продолжать запускать экземпляры для обработки этих запросов. Это то, как Lambda автоматически масштабируется, но не должно ли быть ограничение на количество запускаемых экземпляров? Да, должно быть. Как правило, это определяется на уровне учетной записи, где определяется общее количество экземпляров для всех Lambda в этой учетной записи, но мы можем сделать это для каждой Lambda. Этот номер предоставляется Lambda как зарезервированная емкость.

Получение нашего пользовательского домена

Сначала нам нужно было купить наш собственный домен, а затем создать поддомен, используя его. У нас уже был собственный домен для Zuma, поэтому нам просто нужно было создать поддомен, то есть stage-webhook.‹custom-domain›.com для этапов разработки и контроля качества и webhook.‹custom-domain›.com для этапа prod. . Нам также потребуется создать сертификат SSL-TLS для поддоменов для поддержки HTTPS. И то, и другое можно сделать используя Route53 и ACM.

Предоставление инфраструктуры

Теперь, чтобы фактически предоставить инфраструктуру. Для создания сопоставлений между нашим собственным поддоменом и шлюзом API я использовал плагин в Serverless Framework под названием serverless-domain-manager. Вот файл serverless.yml.

Здесь важно увидеть следующее:

  1. Мы определили разные базовые пути для наших этапов разработки и контроля качества, но не указали базовый путь для производства.
  2. Мы использовали httpApi вместо http, чтобы использовать версию API Gateway V2 или HTTP вместо версии V1 или Rest. Кроме того, нам нужно было объявить apiType: http, endpointType: Regional и securityPolicy: tls_1_2, чтобы подключаемый модуль работал правильно.
  3. Мы только установили выделенную мощность для нашего приема Lambda для производства, но не сделали этого для разработки или контроля качества.
  4. Нам нужно вызвать команду create_domain только для dev, которая будет работать для QA и стадии dev, и снова только для prod.

Еще немного интересных находок:

  1. После успешного предоставления я не мог видеть логику триггера шлюза API, связанную с Lambda, для которой я определил подготовленную емкость, когда смотрел на консоль AWS. Я обнаружил, что когда мы устанавливаем выделенную емкость, создается другая Lambda с выделенным пространством имен.
  2. Было несколько случаев ошибок, когда я начал использовать плагин, и без сервера выдавало ошибку сопоставления API.