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

Часто «бессерверное» иногда рассматривается как решение проблем с традиционной системной архитектурой, позволяющее разработчикам двигаться быстрее и не увязнуть в нюансах инфраструктуры. Это определенно верно в том смысле, что это может увеличить скорость разработки, но это не серебряная пуля для решения всех системных проблем, и иногда это может усугубить существующие проблемы. Приведенные ниже правила призваны помочь избежать некоторых распространенных ошибок при создании бессерверных проектов.

Правило 1: Красивый безсерверный вариант работает лучше.

Бессерверные функции дают много преимуществ, помогая создавать удобный, чистый код. Однако создание работоспособной структуры кода может быть затруднено, в результате чего многие системы страдают от повторяющегося использования кода, мертвого кода в развертывании и больших функций «кухонной раковины» (отсутствие модульного кода).

Простой способ не попасть в эти ловушки — попытаться сохранить традиционные структуры кода и практики. Используйте такие методы разработки, как TDD, повторное использование совместного использования кода между функциями и стандарты линтинга кода, обеспечивающие удобство сопровождения и согласованность кода.

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

  • Модульное тестирование бессерверных функций и кода на уровне модуля для выявления любых ошибок.
  • Интеграционное тестирование, тестирование бессерверных функций от начала до конца, чтобы убедиться, что они работают должным образом. Это может включать тестирование контракта, чтобы убедиться, что функция может действовать или отвечать правильными данными контракта (тела событий и т. д.).
  • Сквозное тестирование, моделирование бессерверного приложения в целом, чтобы убедиться, что все работает при интеграции в систему. Полезно для тестирования данных через систему, производительность и нагрузку/масштабирование.

Правило 2: Сеть очень медленная.

Многие варианты использования бессерверных приложений используют события для передачи данных по системе (например, AWS Lambda и Step Functions). Многие из этих передач событий используют сеть, поскольку именно она дает бессерверным функциям высокий уровень изоляции и возможность запуска по требованию в масштабе. К сожалению, именно это может сделать бессерверные системы медленными, если они спроектированы неправильно.

Всегда учитывайте время, необходимое для прохождения данных (или событий) через всю систему. Например, простой запрос HTTP API из браузера может привести к пяти внутренним запросам к ресурсам для завершения ответа. В зависимости от конструкции системы это может привести к последовательному вызову пяти других бессерверных функций, время отклика каждой из которых будет составлять время отклика HTTP API. Это может быстро увеличить время ожидания запроса браузера до нескольких секунд.

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

Правило 3: сначала строить на случай неудачи.

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

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

Правило 4: Сохраняйте согласованность функций.

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

Согласованности во всей системе также может способствовать наличие стандартного конвейера развертывания, который может проверять, соответствует ли каждая функция набору требований. Функции платформы, такие как инфраструктура как код для определения ресурсов, могут помочь в автоматизации согласованного бессерверного конвейера развертывания. Наилучший подход к конвейерам развертывания бессерверных систем — придерживаться принципа: создать один раз, развернуть в нескольких средах; помогает поддерживать согласованность в различных средах.

Правило 5: Бессерверное решение — не всегда самый дешевый вариант.

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

Это приложение хорошо подходит для бессерверных и не бессерверных архитектур. Глядя на поверхность, будет трудно понять, какова будет стоимость работы между двумя вариантами развертывания. Чтобы получить лучшее представление, лучше всего просмотреть шаблон доступа и требования к использованию для API.

Например, предположим, что API предназначен для веб-сайта ежемесячных соревнований. Трафик API имеет высокий уровень всплесков в начале месяца, когда есть маркетинговый толчок к открытию нового конкурса, и еще один всплеск трафика в конце месяца в прямом эфире. Обычный трафик будет вдвое меньше, чем время пакетной передачи, и соревнование открыто только для жителей Великобритании.

В этом случае мы можем попытаться создать бессерверное приложение, включающее HTTP-шлюз, функцию API для бизнес-правил и бессерверную базу данных для хранения данных, которая будет экономически выгодна для удовлетворения требований. Как правило, бессерверные API-функции оцениваются по запросу за каждый вызов, поэтому они будут иметь более высокую стоимость для всплесков трафика, но минимальные затраты для более низкой скорости трафика после всплесков. Модель оплаты по требованию также позволит сэкономить в ночное время (UTC), когда трафик очень низкий, без дополнительных затрат на поддержание работы простаивающих экземпляров API. БД, такая как AWS Serverless Aurora, также поможет снизить стоимость потребляемой емкости, которая будет увеличиваться и уменьшаться в зависимости от нагрузки запросов.

Если мы немного изменим или требования, чтобы включить обычную фоновую задачу БД, которая извлекает данные для создания отчетов BI, и обновить поведение трафика API, чтобы иметь более постоянную нагрузку в течение месяца, включая более длительное время отклика. Мы быстро теряем некоторые преимущества оплаты за запрос/потребленную мощность, где может быть дешевле использовать ресурс с оплатой за экземпляр (AWS RDS, контейнеры EKS и т. д.).

Если вы нашли эти правила полезными, пожалуйста, поставьте лайк (хлопните в ладоши) и подпишитесь на меня для будущих материалов о бессерверных технологиях / AWS / программировании. Спасибо!