Лучшие практики построения бессерверных микросервисов

Микросервис — забавное слово.

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

Даже если вы никогда не слышали эту фразу раньше, контекстные подсказки довольно просты. Это небольшой сервис. Но что значит «маленький»?

Маленький по размеру? Насколько большим должен быть сервис, чтобы его можно было назвать *средним*?

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

Что такое микросервис?

Проще говоря, микросервис — это независимо итерируемая часть программного обеспечения.

Обычно они являются частями более крупного приложения. Он не должен иметь жестких зависимостей, требующих одновременного развертывания других микросервисов. Он должен быть способен развертываться изолированно.

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

Функциональные зависимости требуют существования других сервисов для решения бизнес-задачи, но не для развертывания.

Как вы решаете, какой микросервис производит события, а какой их потребляет?

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

В классическом примере с «корзиной» у вас есть несколько микросервисов, каждый из которых несет свою ответственность.

Четыре микросервиса, составляющие приложение для корзины покупок

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

Лучшие практики бессерверного подхода

Если рассматривать бессерверные архитектуры, то микросервисные архитектуры подходят для них невероятно хорошо. Бессерверная архитектура хорошо подходит для работы с одной ответственностью, сфокусированной работы — именно в этом и заключается суть микросервисов.

Приведенные ниже лучшие практики предназначены для использования в качестве руководства. Они хорошо зарекомендовали себя в командах, в которых я участвовал, но могут потребовать незначительных корректировок при применении их в ваших проектах.

Репозитории

Есть две школы мысли, когда речь заходит о структуре репозиториев для приложения: монорепо и несколько репозиториев.

Монорепо — это единый репозиторий, в котором есть логические разделения для разных сервисов. Другими словами, все микросервисы будут жить в одном репозитории, но будут разделены разными папками.

Преимущества монорепо включают в себя более легкую обнаруживаемость и управление. К недостаткам можно отнести размер репозитория при масштабировании приложения, большой радиус взрыва при повреждении основной ветви и неоднозначность прав собственности.

С другой стороны, наличие репозитория для каждого микросервиса имеет свои плюсы и минусы.

Преимущества нескольких репозиториев включают четкие границы домена, ясное владение кодом, лаконичные и минимальные размеры репозитория. К недостаткам можно отнести накладные расходы на создание и поддержку нескольких репозиториев и применение последовательных правил управления для всех них.

В случае с serverless я выбираю репозиторий для каждого микросервиса. Это позволяет четко определить, за что отвечает микросервис, и сохранить легкость и целенаправленность кода. Один из принципов проектирования AWS serverless — ничего не делить, и разделение микросервисов на отдельные репозитории позволяет легко избежать случайных действий.

Структура папок

Структура папок в репозитории имеет решающее значение для правильной организации. Убедитесь, что ваш код структурирован таким образом, чтобы его можно было легко найти и поддерживать с течением времени.

При использовании бессерверных микросервисов структурируйте папки корневого уровня по типу ресурсов. Возьмите в качестве примера проект эталонной архитектуры Gopher Holes Unlimited.

Компоновка бессерверных микросервисов

Все функции лямбда содержатся в папке functions. Аналогично, рабочие процессы Step Function содержатся в папке workflows. Лямбда-слои содержатся в папке layers и так далее.

Организация кода по типам ресурсов помогает разработчикам быстро перейти к определенному фрагменту кода.

Внутри каждой из этих папок верхнего уровня находятся подпапки, содержащие все необходимое для отдельного ресурса.

Подпапка, содержащая все файлы, необходимые для лямбда-функции

Возьмем в качестве примера приведенную выше папку для лямбда-функции get-gopher. Она содержит index.js, package.json и package-lock.json. Это означает, что каждая функция может иметь полностью изолированные зависимости, что позволяет вам уменьшить размер пакета Lambda, что в конечном итоге сокращает время холодного запуска.

Обращайтесь с зависимостями каждой из ваших функций отдельно. Если большинство ваших функций используют один и тот же набор пакетов, поместите их в слой зависимостей Lambda и используйте этот слой для всех ваших функций.

Облачные ресурсы

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

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

Когда я только начинал, я подумал, что было бы неплохо разделить ключи KMS между всеми микросервисами, которые я развернул в аккаунте AWS. Я создал микросервис shared-resources и экспортировал значения из стека, которые я должен был использовать в других микросервисах.

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

Не делайте этого.

Заплатите дополнительные $1/месяц, чтобы иметь уникальный ключ KMS в ваших микросервисах. Безопасность всегда стоит того.

Когда дело доходит до определения ваших ресурсов, все должно быть объявлено как Infrastructure as Code (IaC). Это позволит вам последовательно развернуть один и тот же набор ресурсов в любом регионе в любом аккаунте.

Не существует лучшей практики в отношении типа IaC, который вы используете, будь то SAM, CDK, Terraform, Serverless Framework или Pulumi, если вы определили его каким-либо способом, который имеет смысл для вас, то это лучший способ. В будущем, возможно, нам даже не понадобится IaC!

Заключение

Микросервисы и бессерверные технологии идут рука об руку. Они сужают круг обязанностей, дают возможность разделить проблемы и предлагают простой способ оставаться гибкими и быстро развертываться в производство.

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

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

Создавайте самодостаточные сервисы. Не создавайте стеки, для развертывания которых требуются ресурсы других сервисов. Однако вы можете (и должны!) создавать микросервисы, которые зависят от других сервисов для удовлетворения бизнес-процессов посредством свободной связи через вызовы API или события.

Если вы хотите начать работу с микросервисами, не забывайте, что их основой является домен. Если вы хотите «разрушить монолит», начните с определения отдельных частей вашего приложения. Найдите области приложения, которые имеют достаточно бизнес-логики, чтобы быть самостоятельными и итерироваться отдельно от всего остального.

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

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

Счастливого кодинга!

Оцените статью
devanswers.ru
Добавить комментарий