
Здравствуйте, товарищи! Недавно мне понадобилось сделать простой бэкенд для онлайн-песочницы в своем open source проекте. Сейчас для таких задач есть много конструкторов и low-code решений, типа n8n. Но я "по старинке" решил взять serverless с лямбдами, поскольку в позапрошлой компании плотно работал с этим стеком.
Вспоминая тему serverless, я обнаружил, что в русскоязычном пространстве, и на Хабре в частности, почти не освещена одна полезная техника. Пришло время исправить ситуацию и заполнить пробел данной статьей!
Немного базы
Когда мы работаем в serverless стеке, большая часть логики у нас исполняется в облачных функциях или так называемых лямбдах. Такое название пошло из одноименного сервиса в AWS, которые первыми реализовали эту технологию. В двух словах и упрощенно напомню суть лямбд: на каждый триггер (запрос/таймер/etc) запускается новый экземпляр рантайма (доступно много языков) на серверах провайдера. Там исполняется наша функция, которую мы предварительно загрузили. Как только она отрабатывает - экземпляр умирает.
Проблема
Как правило, функции для работы в лямбдах делают маленькими и делают их много на разные триггеры. Классический паттерн: есть api gateway в отдельном сервисе, где прописаны наши эндпоинты. На каждый эндпоинт делаем отдельную лямбду.
Это база и для многих проектов на старте такой вариант подойдет. Но тут есть 2 очевидные проблемы:
сложнее поддерживать и деплоить проект
усугубляется vendor-lock
Причем второе намного опаснее. Известный факт, что с определенной нагрузки, лямбды становятся явно дороже, чем обычный сервер, который работает постоянно. Появляется следующая перспектива: ваш проект полетел, нагрузка сильно возрастает и вы начинаете платить за лямбды сильно больше. Но поскольку у вас вся архитектура заточена под serverless, просто так переехать на обычный сервер вы уже не можете - придется все переписывать. На это и рассчитывают хитрые облачные провайдеры.
Что делать
Хорошим решением является паттерн, который я назвал "Монолитная лямбда". Как выяснилось позже, в англоязычном сегменте он известен как Lambdalith. Рассмотрим его реализацию на Node.js, поскольку в serverless я работал именно с ним. Суть паттерна в следующем:
пишем обычное монолитное приложение, используя мини-фреймворк, типа fastify
добавляем адаптер для запросов из api gateway
собираем приложение в бандл с помощью любого сборщика фронтенда, типа Webpack
создаем лямбду в консоли облачного провайдера и загружаем в нее наш бандл
profit!
Преимущества
не требуется делать особую организацию проекта и деплой. Да, для лямбд есть специальные фреймворки, но с ними тоже надо разбираться и свои подводные камни там наверняка есть
при нормальной архитектуре (слои, порты/адаптеры, DDD, etc), vendor-lock снижается почти до нуля. Если проект летит - просто отцепляете адаптер для api и у вас обычный монолит, который можно запустить где и как угодно
На позапрошлой работе мы использовали этот паттерн на всех продуктах и дела шли четко. Даже когда одно наше IOS-приложение залетело в топ-5 AppStore Бразилии, и к нам приходило по 10+ тысяч пользователей в день.
Слабые стороны
Да, такая лямбда будет запускаться и работать подольше обычной, но не значительно. Еще я бы отметил, что Нода тут превращается в классический PHP и теряет большую часть своих преимуществ. Кое-где даже приходится писать код по-другому: ждать асинхронных операций там, где обычно ненужно. Поэтому при переходе на сервер, кое-что надо будет отрефакторить для улучшения перфоманса.
Выводы
Стоит понимать, что этот паттерн больше подходит для стартапов и MVP. Когда нам надо быстро стартовать и проверить гипотезу. Если не полетит - нестрашно, поскольку на инфраструктуру мы потратим почти 0 времени и денег. А если полетит - относительно легко спрыгнем с лямбд и запустим обычный монолит.
Кроме того, для некоторых продуктов, даже когда это рабочий бизнес, хорошо подойдут маленькие лямбды. Например, какой-то b2b сервис с малым количеством запросов, но с длинным пайплайном их обработки и сложной инфраструктурой.
Кстати, если вы хотите попробовать настоящий serverless (вообще без бэкенда), то рекомендую посмотреть на стек $mol + Giper Baza (ex CRUS-DB). Там из коробки идет Local-First, децентрализация, шифрование и еще много полезного.
На этом все! Подписывайтесь на мой телеграм-канал, ставьте звезды на гитхабе, ну и буду рад видеть ваши комменты!
