Comments 38
Получается, вы начали делать работу по распилу без вопроса "зачем" и оказалось, что это никому не нужно?
Я хотел разбить логику на чуть более большие куски, чтобы каждому досталось не больше двух-трёх сервисов
Никогда не встречал ситуации, где количество микросервисов превышает количество разработчиков. Бывало, что команда поддерживала два-три микросервиса, но размер команды был больше трех человек. И в большинстве случаев, микросервисы были просто удобным способом дать работать нескольким командам параллельно.
Удобство "deploy" в этом случае оправдывает возрастающую сложность по сравнению с монолитом?
Нам по наследству достался проект, в котором (совсем не микро) сервисов было шесть, а разрабов два, и половина фронтэндера, на вторую половину работавшего аналитиком. Причём достался он востребованный в проде, но предыдущая команда аутсорсеров, получившая его от разогнанной пред-предыдущей команды и более-менее запустившая, работала с нами не более месяца. В итоге и всё развитие, и баги, и девопс лежал на нас двоих параллельно с изучением, причём напарник был свежим (но толковым, по счастью) миддлом.
Весело было.
Лично работаю над таким проектом. На бекенде около 7 МС и в настойщий момент 1 разработчик (на поддержке)
Но на момент активной разработки все равно было не больше 4х бекендеров единовременно
Но на момент активной разработки все равно было не больше 4х бекендеров единовременно
И почему выбрали такую архитектуру, а не монолит?
На самом деле сложилось много факторов. Но в нашем случае это дает возможность экономить на мощностях (нагрузка на МС сильно неравномерная, на одном должен быть хайлоад, на других - опционально), устряняет (почти) одну точку отказа и позволяет часть функционала резервировать.
Более предметно ответить не могу, не полностью владею вопросом, да и NDA никто не отменял.
В чём проблема даже одному специалисту поддерживать десяток микросервисов, если они действительно "микро"?
Проблем нет, вопрос в причине использования микросервисов, вместо монолита, если нет десятков программистов, которые очевидно будут "толкаться локтями" работая над единым монолитом, и поэтому приходиться делить на команды, и каждой команде выдавать отдельную "песочницу", чтобы они там "игрались".
МС это все же не столько про распределение работы между командами. Это тоже важно и одно из полезных следствий такой архитектуры, но в первую очередь исходят из доменной специфики. Если какие-то сервисы никаким образом между собой не связаны, но им надо быть раздельными. Иначе получаются такие микромонолиты из не связанной бизнес логики, что тоже можно сказать антипаттерн. Потом людей станет больше и чего с этим делать? Либо вообще не начинать сервисы пилить, либо уж делать их корректно. Самое главное это держать каждый сервис в ответственности одной команды.
Если какие-то сервисы никаким образом между собой не связаны, но им надо быть раздельными
Не очень понятно. В современных языках программирования есть модули, есть способ объедения модулей в единую сущность, назовем это пакетом. Можно выделить разные "домены" в отдельные пакеты. Чем этот подход хуже в условиях когда у нас есть один программист на все про все?
Это уже другой вопрос вообще. Я писал конкретно про "Никогда не встречал ситуации, где количество микросервисов превышает количество разработчиков". В этом ничего плохого я не вижу, и какие лучшие практики микросервисной архитектуры это нарушает тоже.
А то, что вы описываете, конечно ничего в этом плохого нет. Модульный монолит нынче модная штука. Лучше или хуже это микросервисов зависит от конкретного кейса.
Именно тот самый. Если у вас 3 разработчика и перспектива (реальная) расширения до 6 в течении года, то вам не нужны микросервисы. Вообще.
Просто пишите нормально монолит. И всё будет хорошо. Современные языки имеют достаточно выразительных средств для этого.
Архитектура приложения и размер команды связаны чуть менее чем никак. Это ортогональные вопросы совершенно.
Не совершенно. От размера команды зависит количество нового кода. Практически линейно. И количество знаний которые надо держать в голове для работы с эти кодом зависит от размера команды. И даже басфактор не может быть больше размера команды.
Все очень плотно связанно.
По моему опыту микросервисы именно про команды: если у вас стопицот разработчиков и им тесно в монолите (постоянные мерж-конфликты, размазанная ответственность, side effects, конфликтный деплой).
Иначе же можно просто запилить модульный монолит и не задумываться о всех головных болях микросервисов.
Мне кажется, что модульность (не всегда и не везде это классические микросервисы) - это прежде всего про масштабы комплекса целиком. И про масштабы изменений относительно всего комплекса.
У нас... Ну, допустим, несколько десятков тысяч программных модулей (кто их вообще считал). И сотни полторы разработчиков.
Каждый модуль реализует какую-то свою бизнес-логику. Законченный ее кусок - "получить на вход это и сделать с ним вот это".
И понятно, что этот кусок может потребовать изменения в связи с изменением какого-то процесса. Или появится новый процесс под который будет написан новый модуль. Могут таже быть "программные комплексы", состоящие из "диспетчера" и нескольких модулей (диспетчер получает на вход набор данных и по нему уже сам решает через какие из модулей эти данные нужно прогнать).
Все зависимости исключительно на уровне версий - есть единый реестр поставок где хранятся мнемоники и установленные версии. Есть понятие "пререквизита" - "данная поставка требует чтобы в юните была установлена поставка с мнемоникой MNM и версией NNN" - это проверятся инсталлятором - нет установленного пререквизита - не будет установки.
В общем и целом это работает.
Напротив, микросервисы - это исключительно про масштабируемость: разнесение по разным компам и увеличение количества запущенных экземпляров.
А кто вам мешает немикросервисы пошардировать и разнести по разным компам? Это уже минимум лет 30-40 назад научились делать.
Монолитность, как правило, и мешает. Мягко говоря, практически всегда невозможно какую-то, тесно переплетённую с остальным куском монолита, функцию распараллелить на пачку серверов с балансировщиком нагрузки.
Почему? Паралелим естественно весь сервис. Затраты времени на старт приложения работающего неделями и месяцами считаем несущественными.
Люди уже 30-40 лет успешно так делают. Или это утраченные знания предков?
Допустим, 100 копий монолита на 100 серверах. Поставить впереди лёгонькую проксю и размазывать запросы по нодам. В какой момент мне нужен микросервис?
Это уже другой вопрос вообще. Я писал конкретно про "Никогда не встречал ситуации..."
Ну это мой личный опыт, понятно что у других другой опыт. Поэтому это как раз было утверждение, а вопрос там был "в этом случае оправдывает возрастающую сложность по сравнению с монолитом?"
Да можно просто в виде набора программ и/или функций в динамических библиотеках.
Ну вот пример из личного - есть комплекс проверок в рамках контроля платежей. Работает в режиме очень высоких нагрузок т.к. через него проходит каждый платеж.
У этого комплекса есть "диспетчер" куда передаются данные о платеже. И есть набор (сейчас около десятка) атомарных проверок. Диспетчер анализирует платеж (плательщик, получатель, валюта, тип платежа - входящий, исходящий, внутренний) и на основании этого уже по настройкам выстраивает цепочку проверок для данного конкретного платежа - в каком порядке и что вызывать. Ну и вызывает их по цепочке пока какая-то не скажет что "не пройдено" - этот результат уже возвращается наверх.
Каждая проверка - отдельный программный модуль. Понадобится что-то новое - просто написать еще один модуль и добавить в настройки. Это все делается "на горячую". Порядок, список проверок для каждого конкретного случая - все это в настройках. Гибко, настраиваемо, модульно.
Не надо распиливать монолит. Надо отколупывать от него то, что плохо держится.
Не совсем понятно зачем начали улучшать и так работающее.
Само по себе "распилить немодный монолит на модные микросервисы" ну такое себе занятие. Разве что совсем время девать некуда.
Но если уж пилить, то пилить с умом. Не ориентироваться на размер, но на функциональное назначение. Каждый сервис должен выполнять какую-то конкретную с точки бизнес-логики задачу. Тогда упрощаются любые изменения, вызванные изменениями бизнес-логики - новые бизнес-процессы, изменение условий и требований в уже существующих.
Ну и архитектуру всего этого должен выстраивать человек, понимающий предметную область.
Ну и возможно стоит обратить внимание на старую добрую модель акторов.
Оно работало, но добавлять в него новый функционал было очень сложно — потому и решили распилить
Осмелюсь предположить))) По описанию классическое манагерское MVP, когда нет четкого плана как выглядит продукт целиком, сначала скорее всего какую то фичу сделали или несколько, а потом пошли правки, правки, правки ну и на 150 итерации всем уже плевать было как что там работает, и начался dependency hell, и каждый релиз создавал новые баги, и тут и вспоминают о микросервисах, в надежде на то что код изолируется и баги уйдут)))
Скорее всего, да. Начали без четкого понимания что будет в оконцовке, прикручивали одну фичу за другой (все что на ум пришло по дороге), дошли до состояния когда оно начало рушится под собственным весом. Пришли к тому, что надо все переписывать. И решили переписать все уже модульно. Обозвали это модным словом "пилим монолит". Но поскольку нормальная организация процесса где есть архитекторы, аналитики - это "фи, энтерпрайз какой-то, у нас тут все молодые-свободные и вообще стартап", то опять ни до чего не договорились, только разосрались, на то все и закончилось.
Вывод напрашивается сам собой - монолит не нужно распиливать, ему нужно поклоняться и желания загадывать)
Наш техдир принял решение
сбросить всю ответственность с себятактически отступить и сказал: «делайте как хотите, я ни хрена не понимаю».
Вот где-то здесь все и пошло не так. Техдир, по сути, должен был выступать тем самым техлидом, который бы установил четкие для всех правила и взял на себя ответственность за них. Но ок, он с этим не разбирается (тогда спрашивается, а какой это нафиг техдир, ну да ладно). Значит эту задачу должен был взять следующий по цепочке - тимлид. Споры и обсуждения это хорошо и полезно, архитекторы должны вовлекать других в подобных большие вопросы, но в конечном итоге надо в какой-то момент твердо сказать - делаем так то так то потому то потому то.
Предварительно менеджер и техдир (и тимлид, раз он тут архитектор главный стал) таки должны были обрисовать план, зачем это бизнесу надо. Какие конкретно метрики это улучшит. Нужно ли реально было все переделывать или достаточно было рефакторинга и подумать немного про архитектуру.
Ну и конечно же, монолиты, в зависимости конечно от размера, обычно "душат". Отколупливают изолированный функционал в новые сервисы, а новый функционал сразу пишут в отдельных сервисах. Иначе "бэкэнд 2.0" может никогда так и не уйти в продакшен.
Я сторонник микросервисов, но, так как они часто реализуются, блин, для тех кто такое делает особое место в аду должно быть. Имеем сейчас типа "микросервисный" проект, где мало того, что все засунуто в одну монорепу, так еще все вообще засунуто в один солюшен, с зависимостями не через пакеты, как положено, а через <ProjectReference>
В результате над всей этой конструкцией даже чихнуть страшно, чтобы она от своей дичайшей связанности не развалилась. Если так делать, то уж пусть лучше будет монолит - хотя бы не будет всех проблем с кучей процессов и их взаимодействием между собой.
Модульность вообще хорошо. Но только когда каждый модуль независим от остальных и выполняет свою конкретную задачу. Разные модули вообще могут быть написаны на разных языках и все зависимости между ними исключительно на уровне версий и не более.
Но все это требует качественной архитектурной проработки. А делать "микросервисы ради микросервисов" - порочно. Как и любая концептуальность ради концептуальности.
Где-то микросервис может быть действительно "микро". А где-то это может быть небольшой такой мололитик просто потому что он реализует какой-то один кусок бизнес-логики, который нет смысла дробить дальше (хотя бы потому, что это порождает лишние зависимости).
Как НЕ надо распиливать монолит