Найти тему

Почему так важно правильно декомпозировать на микросервисы и как это сделать

Оглавление

А в чём, собственно, проблема?

Для понимания проблемы сначала стоит вспомнить, чем хороши микросервисы и плохи монолитные приложения.

Основные проблемы монолитов:

  • Чрезвычайно затруднена и замедлена совместная работа, приходится разрешать много конфликтов в коде;
  • Приходится делать релиз целиком всего приложения, даже если изменилась одна запятая на второстепенном экране. Чревато ошибками и проблемами при релизе;
  • Сильная связанность затрудняет понимание и разработку внутренность приложения - всё сильно переплетено и расцепить часто вообще невозможно;
  • Если что-то одно падает, то падает сразу всё.

Микросервисы решают все эти проблемы:

  • Микросервис - совершенно независимое, полностью отдельно работающее приложение. Другие микросервисы никак от него не зависят. Т.е. если один микросервис падает, то другие продолжают работать
  • Полностью отдельные, независимые и непересекающиеся релизы в пром. Нет влияния микросервисов друг на друга.
  • Объем кода несравнимо меньше кода монолита. В нём легче разбираться и конфликтов гораздо меньше
  • Отдельные команды могут развивать микросервисы независимо. Релизы разные, в разное время и с разной частотой.
Изображение из Интернет
Изображение из Интернет

Часто систему неправильно разделяют (декомпозируют) на микросервисы, что полностью сводит на нет все их преимущества:

  • Неправильная декомпозиция приводит к созданию "божественных" супер-классов в каждом из сервисов;
  • Код дублируется, пересекается по функциями, не применяется принцип единственной ответственности;
  • Не достигается слабая связанность и т.о. сервисы сильно зависят друг от друга и если падают, то падают все вместе

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

Существуют два взаимодополняющих подхода к декомпозиции на микросервисы:

  • По бизнес-умениям / областям
  • По доменной модели

Микросервисы на базе бизнес-умений/областей

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

Примеры бизнес-областей:

  • Управление складом (приходно-расходные операции, хранение)
  • Управление поставщиками (расчёты с подрядчиками/поставщиками)
  • Управление внутрихозяйственной деятельностью (закупки, договора)
  • Управление снабжением (формирование потребности в снабжении, ведение норм и стандартов снабжения, работа с поставщиками, контрактами)

Казалось бы всё нормально, но если посмотреть внимательно, то все сервисы включают в себя работу с одинаковыми типами объектов: договорами, контрактами, заказами, SKU и PLU, подрядчиками, сотрудниками и проч.

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

В результате такие микросервисы превращаются в "божественные классы", которые умеют делать все и повторяются из сервиса в сервис.

Это плохо и неправильно, потому что сводит на нет все преимущества микросервисов.

Микросервисы на базе доменной модели

Второй подход, не имеющий подобной проблемы - проектировать классы на основе доменной модели.

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

Как это делается:

Разработчики и Бизнес договариваются о Едином Языке и выделяют Термины, которые и будут составлять основу доменной модели.

Термины выделяются из функциональных требований, например, написанных как User Story.

Далее очерчиваются границы поддомена. Это делается для того, чтобы точнее понять какие термины входят в границы поддомена.

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

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

Есть два дополнительных принципа, помогающих разделению на микросервисы:

Принцип единственной ответственности

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

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

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

Принцип максимальной близости

В микросервис выделяются т.н. Агрегаты - блоки настолько близкие друг-другу, что меняются все вместе.

Рассмотрим пример с машиной. Колесо машины не имеет смысла в отдельности от конкретной машины. Если какая-то запчасть машины сломается, то перестанет ехать вся машина целиком.

Это и есть Агрегат, когда изменения в любой из частей агрегата меняются весь Агрегат в целом.

Еще один пример Агрегата - Кредитная история. При добавлении нового платежа по кредиту или взятия нового кредита пересчитывается вся кредитная история целиком.

Всё, что входит в Агрегат можно смело выделить в отдельный микросервис.

Размер микросервисов

Влияет ли размер (по количеству Терминов в поддомене) на декомпозицию микросервисов?

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

Поэтому сервисы не желательно делать слишком маленькими.

Алгоритм декомпозции

Что же получаем в итоге?

  • Независимо работающие сервисы со слабой связанностью. Если падает один из них, остальные продолжают работать
  • Удобство, быстрота и независимость разработки и развёртывания

Подведём итог и сформулируем правильный алгоритм декомпозиции на микросервисы:

  • Начать с функциональных требований. Представить их в виде пользовательских историй
  • Выделить системные операции
  • Выделить общие Термины, домены и поддомены
  • Составить таблицу Терминов и системных операций
  • Разбить на микросервисы в соответствии с границами поддоменов
  • Определить взаимодействие между микросервисами и при необходимости изменить границы поддоменов
  • Распределить системные операции между микросервисами

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

Буду рад Вашим вопросам в комментариях.