Доброго времени суток! Для начала, о чем будет статья? Статья является сжатым описанием опыта перехода от монолитного приложения к микросервисам. Коснемся плюсов такого перехода и затронем часть проблем, с которыми можно столкнуться в реальной разработке. Для кого может быть полезна статья? Для тех кто по каким-то причинам еще сомневается в эффективности микросервисных архитектур. Также отмечу, что статья не является учебным пособием. Она ставит целью коротко познакомить с практикой перехода от одной архитектуры к другой. Для тех кто хочет погрузиться в детали проектирования микросервисных архитектур, рекомендую почитать литературу, начать можно с книги Криса Ричардсона «Микросервисы. Паттерны разработки и рефакторинга.». Это даст неплохую основу для дальнейшего развития. Излагать материал буду на примере построения гипотетической системы регистрации и онбординга продавцов на некоторой торговой площадке.
Что дано?
Система регистрации, которая хранит информацию о продавце и его магазине, реализует процесс заполнения и хранения юридических данных. Управляет процессами проверки и одобрения данных продавца, проверки и подписания договора между торговой площадкой и продавцом, процессы знакомства продавцов с основными частями и инструментами используемыми в процессе работы на площадке. Также реализует систему поощрения активных продавцов и наказания недобросовестных. Забегая вперед, по ходу статьи добавится еще функциональность дочерних аккаунтов. Наглядно это может выглядеть так.
Погрузимся в историю.
В самом начале зарождения проектов обычно нет точного и четкого понимания что будет в системе и какие функции она будет выполнять. Тут стоит понимать, что это нормальная ситуация в случаях, когда вы не занимаетесь копированием. Требования в самом начале обычно похожи на «нужно получить какие-нибудь данные». Соответственно, разработка реализует первые потребности. То, что мы имеем в дано - это результат определенного промежутка времени. Тут же можно заметить одну из проблем разработки микросервисов. В самом начале проблемой является неопределенность. Что за сервисы нужны, их количество и назначение. Тут же приведу еще одну особенность, которая порой стимулирует рост именно монолитов в энтерпрайзе. Ни для кого не секрет, что по мере роста компаний растут и процессы управления. И может возникнуть ситуация, когда разработка микросервисов вполне допустима, но получение ресурсов - это процедура различных согласований и одобрений, при этом не всегда быстрая и легкая.
Что же можно сделать, чтобы попытаться избежать роста монолита в самом начале жизни проекта?
Первое и наверное самое важное - это наличие опыта. Если вам доводилось строить похожие системы, то это позволит хотя бы прогнозировать возможные дальнейшие шаги. А если спуститься к более реальным вещам - это пристальное внимание к симптомам монолита. Именно в начале жизни проекта важно регулярно анализировать его функциональность. Попробуем на нашем примере. В самом начале мы просто собираем данные.
Но вот в какой-то момент становится заметно, что данные достаточно четко разделяются по доменам. И если вы это видите, значит пришло время посмотреть на возможность разделения. Возможно стоит организовать отдельно сервис сбора данных о продавце и отдельно данных о магазине.
Следующий симптом - выделить объем и сложность приложения. Тут нельзя привести точной меры в виде если у вас 1К строк кода это еще нормально, а 1001 это уже монолит. Нет, мерой скорее является тот момент, когда вы начинаете все более активно применять различные шаблоны проектирования. Причем не просто какие-то фабрики или стратегии и цепочки обязанностей, a именно разбиение на модули, создание каких-то фасадов. Когда список того, что делает приложение уже не получится перечислить условно по пальцам одной руки. Это тоже признак того, что возможно стоит разделить приложение на несколько более простых.
Проектирование
Первая итерация - это разбиение на микросервисы по доменам или основным задачам. В нашем случае это проделано на этапе дано. Итого, в первом подходе получаем 8 сервисов.
Теперь, когда начала проявляться система, самое время еще раз посмотреть уже более детально на задачи этих сервисов. Основная причина - это попытаться исключить дублирование кода, а так же постараться обеспечить принцип единственной ответственности для сервисов. Попробуем сделать это на нашем примере. У нас есть процесс одобрения продавца и процесс подписания договора. Оба они скорее всего инициируют запуск бизнес процесса в системе управления бизнес процессами(BPMS) и потом реагируют на его результат.
Можно предположить, что работа с системой управления бизнес процессами не всегда тривиальна -из опыта: API методы часто имеют достаточно специфичный набор заголовков, часто в них содержатся вычисленные сигнатуры для подписи запроса, различные метки времени. Учитывая, что у нас как минимум 2 сервиса будут работать с системой управления бизнес процессами, можно сделать вывод, что у нас будет обильное дублирование кода. В дополнение ко всему для запросов могут применяться ключи для генерации сигнатур или какого-либо шифрования - это значит, трудности по поддержанию актуальности этих ключей, а так же нам необходимо получать результаты обработки из BPMS. Исходя из рассуждений напрашивается вывод, что эту деятельность стоит вынести в отдельный сервис, который станет фасадом облегчающим взаимодействие.
Анонсированное расширение возможностей системы регистрации
Как мы помним, каждый продавец кроме своего аккаунта может создавать еще дочерние аккаунты (в случае когда у продавца есть несколько менеджеров, занятых управлением торговлей). Поэтому снова смотрим на наше разбиение и видим, что можно выделить еще один сервис - процесс регистрации. Чем будет заниматься такой микросервис: его основной задачей будет хранение шагов регистрации продавца и дочерних аккаунтов. Процесс заполнения данных может состоять из разветвленного дерева шагов, на каждом из которых заполняется свой набор данных, производится своя специфическая валидация. Переходы между шагами могут иметь сложный набор правил.
Соберем теперь части нашей системы в одно целое:
Итог
В этой статье мы рассмотрели причины возникновения монолитов и один из примеров как можно поделить его на микросервисы.
В следующей статье посмотрим как строится взаимодействие между сервисами и на проблемы проектирования в микросервисной архитектуре.
Комментарии (6)
shai_hulud
06.12.2021 20:23Вопрос к автору. Можно ли построить микросервисное приложение в одном процессе? А в одной кодовой базе?
fougasse
06.12.2021 22:37Можно.
Но нужно ли?
shai_hulud
07.12.2021 00:30только для @fougasse
Ну если как у автора цель "поделить" код, то поделить "можно" и в рамках одного процесса/кодовой базы. Получить изоляцию логики, не поимев проблем с межсервисным взаимодействием (транспортом), деплойментом и версионированием.
В статье вроде ничего про команды разрабатывающими на разных языках, лайв деплоймент, маштабировании итд не было, только "у нас всё пишется в один файл, сейчас мы внедрим микросервисы и заживем".
oleg-m1973
Не бывает никаких "монолитов" и "микросервисов". Есть декомпозиция системы на физические и логические модули. Просто не надо превращать систему в помойку, тогда и скакать от "монолита" к "микросервисам" не понадобится.
shai_hulud
Т.е. вы говорите что есть "монопомойка" и парни разбили ее на "микропомойки"?
oleg-m1973
Нет. Я говорю, что в большинстве случаев, когда речь заходит о монолитах-микросервисах, это значит что парни просто не владеют навыками проектирования. В результате получится та же помойка, только сбоку. Но, справедливости ради, надо сказать, что микросервисы всё-таки заставляют этих парней учиться декомпозиции.