Всем привет, на связи Юджин, (теперь уже) беспризорный backend-разработчик на Go. Сегодня я расскажу вам забавную и больную историю о том, как мы монолит распиливали. Кто-то, может, посмеётся, а может, найдёт в этом себя. Никого ничему не учу, потому что сам ничего не умею.

Предыстория

Настоящие имена и названия называть не буду, поэтому пройдёмся по условным обозначениям:

  • Антон: наш технический директор, кофаундер стартапа

  • Максим: наш тимлид

  • Кирилл: главный менеджер, кофаундер

  • Алексей: бэкендер

  • Борис: инвестор

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

Началось всё с того, тот самый хороший друг фуллстек-разработчик пригласил меня в околокриптостартап. Сам он туда попал с фриланса, когда выполнил несколько их заказов.
На момент моего попадания в стартап (примерно 1-2 месяца после его зарождения) был написан монолитный бэкенд (Node.js + Fastify) и что-то похожее на фронтенд (React) - всё это написано за 1-2 месяца одним человеком в спешке. Всё работало прекрасно до момента, когда около нас начал образовываться второй проект, который писали другие разработчики на аутсорсе. Не хватало фич, которые в монолит запихнуть было очень тяжело. На тот момент команда увеличилась - и вот нас уже 3 программиста и 3 фронтендера. Каждый работал над своими частями проекта, никто никому не мешал, всем мешал только написанный в спешке бэкенд.

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

Первые проблемы

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

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

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

«Уютный стартап» — говорили они.

В итоге, каким-то образом, мы выбрали использовать RestAPI, но чтоб он выглядел как gRPC, и большие микросервисы. Принялись писать.

Писали сервисы по мере важности, постепенно заменяя логику в монолите на запросы к сервисам, всё по красоте, всё круто.

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

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

Последние проблемы

Где-то на середине Кирилл с Борисом подмышкой решили сделать пивот в обратную сторону и отменить половину идей, которые мы уже реализовали в старом бэкенде и начали реализовывать в новом. Снова пришлось переобдумывать архитектуру.

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

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

Вывод

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

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

Комментарии (33)


  1. sanneo
    11.06.2023 10:26
    +25

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


    1. EugeneKannou Автор
      11.06.2023 10:26

      Изначально вопрос был и ответ на него тоже был, нам всё одобрили. А потом начальство решило, что нам уже это не надо и отменил разработку


  1. apro
    11.06.2023 10:26
    +3

    Я хотел разбить логику на чуть более большие куски, чтобы каждому досталось не больше двух-трёх сервисов

    Никогда не встречал ситуации, где количество микросервисов превышает количество разработчиков. Бывало, что команда поддерживала два-три микросервиса, но размер команды был больше трех человек. И в большинстве случаев, микросервисы были просто удобным способом дать работать нескольким командам параллельно.

    Удобство "deploy" в этом случае оправдывает возрастающую сложность по сравнению с монолитом?


    1. rombell
      11.06.2023 10:26

      Нам по наследству достался проект, в котором (совсем не микро) сервисов было шесть, а разрабов два, и половина фронтэндера, на вторую половину работавшего аналитиком. Причём достался он востребованный в проде, но предыдущая команда аутсорсеров, получившая его от разогнанной пред-предыдущей команды и более-менее запустившая, работала с нами не более месяца. В итоге и всё развитие, и баги, и девопс лежал на нас двоих параллельно с изучением, причём напарник был свежим (но толковым, по счастью) миддлом.
      Весело было.


    1. p07a1330
      11.06.2023 10:26

      Лично работаю над таким проектом. На бекенде около 7 МС и в настойщий момент 1 разработчик (на поддержке)
      Но на момент активной разработки все равно было не больше 4х бекендеров единовременно


      1. apro
        11.06.2023 10:26
        +1

        Но на момент активной разработки все равно было не больше 4х бекендеров единовременно

        И почему выбрали такую архитектуру, а не монолит?


        1. p07a1330
          11.06.2023 10:26

          На самом деле сложилось много факторов. Но в нашем случае это дает возможность экономить на мощностях (нагрузка на МС сильно неравномерная, на одном должен быть хайлоад, на других - опционально), устряняет (почти) одну точку отказа и позволяет часть функционала резервировать.
          Более предметно ответить не могу, не полностью владею вопросом, да и NDA никто не отменял.


    1. cat_chi
      11.06.2023 10:26

      Никогда не встречал ситуации, где количество микросервисов превышает количество разработчиков

      Странно. В чём проблема даже одному специалисту поддерживать десяток микросервисов, если они действительно "микро"?


      1. apro
        11.06.2023 10:26

        В чём проблема даже одному специалисту поддерживать десяток микросервисов, если они действительно "микро"?

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


        1. Leetc0deMonkey
          11.06.2023 10:26
          +1

          Работая над монолитом не "толкаются локтями". Модульной разработке уже 100 лет, и она отлично себя зарекомендовала. Но вот в айти набежали дети, откуда им это знать. А поскольку эти дети ещё и неспособны принимать критику, прячась за премодерацией, то перспективы совсем печальны.


    1. creker
      11.06.2023 10:26

      МС это все же не столько про распределение работы между командами. Это тоже важно и одно из полезных следствий такой архитектуры, но в первую очередь исходят из доменной специфики. Если какие-то сервисы никаким образом между собой не связаны, но им надо быть раздельными. Иначе получаются такие микромонолиты из не связанной бизнес логики, что тоже можно сказать антипаттерн. Потом людей станет больше и чего с этим делать? Либо вообще не начинать сервисы пилить, либо уж делать их корректно. Самое главное это держать каждый сервис в ответственности одной команды.


      1. apro
        11.06.2023 10:26

        Если какие-то сервисы никаким образом между собой не связаны, но им надо быть раздельными

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


        1. creker
          11.06.2023 10:26

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

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


          1. BugM
            11.06.2023 10:26

            Именно тот самый. Если у вас 3 разработчика и перспектива (реальная) расширения до 6 в течении года, то вам не нужны микросервисы. Вообще.

            Просто пишите нормально монолит. И всё будет хорошо. Современные языки имеют достаточно выразительных средств для этого.


            1. creker
              11.06.2023 10:26

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


              1. BugM
                11.06.2023 10:26

                Не совершенно. От размера команды зависит количество нового кода. Практически линейно. И количество знаний которые надо держать в голове для работы с эти кодом зависит от размера команды. И даже басфактор не может быть больше размера команды.

                Все очень плотно связанно.


              1. KGeist
                11.06.2023 10:26

                По моему опыту микросервисы именно про команды: если у вас стопицот разработчиков и им тесно в монолите (постоянные мерж-конфликты, размазанная ответственность, side effects, конфликтный деплой).

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


                1. SpiderEkb
                  11.06.2023 10:26

                  Мне кажется, что модульность (не всегда и не везде это классические микросервисы) - это прежде всего про масштабы комплекса целиком. И про масштабы изменений относительно всего комплекса.

                  У нас... Ну, допустим, несколько десятков тысяч программных модулей (кто их вообще считал). И сотни полторы разработчиков.

                  Каждый модуль реализует какую-то свою бизнес-логику. Законченный ее кусок - "получить на вход это и сделать с ним вот это".

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

                  Все зависимости исключительно на уровне версий - есть единый реестр поставок где хранятся мнемоники и установленные версии. Есть понятие "пререквизита" - "данная поставка требует чтобы в юните была установлена поставка с мнемоникой MNM и версией NNN" - это проверятся инсталлятором - нет установленного пререквизита - не будет установки.

                  В общем и целом это работает.


          1. apro
            11.06.2023 10:26

            Это уже другой вопрос вообще. Я писал конкретно про "Никогда не встречал ситуации..."

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


        1. SpiderEkb
          11.06.2023 10:26

          Да можно просто в виде набора программ и/или функций в динамических библиотеках.

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

          У этого комплекса есть "диспетчер" куда передаются данные о платеже. И есть набор (сейчас около десятка) атомарных проверок. Диспетчер анализирует платеж (плательщик, получатель, валюта, тип платежа - входящий, исходящий, внутренний) и на основании этого уже по настройкам выстраивает цепочку проверок для данного конкретного платежа - в каком порядке и что вызывать. Ну и вызывает их по цепочке пока какая-то не скажет что "не пройдено" - этот результат уже возвращается наверх.

          Каждая проверка - отдельный программный модуль. Понадобится что-то новое - просто написать еще один модуль и добавить в настройки. Это все делается "на горячую". Порядок, список проверок для каждого конкретного случая - все это в настройках. Гибко, настраиваемо, модульно.


  1. YegorP
    11.06.2023 10:26
    +8

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


  1. SpiderEkb
    11.06.2023 10:26
    +2

    Не совсем понятно зачем начали улучшать и так работающее.

    Само по себе "распилить немодный монолит на модные микросервисы" ну такое себе занятие. Разве что совсем время девать некуда.

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

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

    Ну и возможно стоит обратить внимание на старую добрую модель акторов.


    1. EugeneKannou Автор
      11.06.2023 10:26

      Оно работало, но добавлять в него новый функционал было очень сложно — потому и решили распилить


    1. SaintSet
      11.06.2023 10:26

      Осмелюсь предположить))) По описанию классическое манагерское MVP, когда нет четкого плана как выглядит продукт целиком, сначала скорее всего какую то фичу сделали или несколько, а потом пошли правки, правки, правки ну и на 150 итерации всем уже плевать было как что там работает, и начался dependency hell, и каждый релиз создавал новые баги, и тут и вспоминают о микросервисах, в надежде на то что код изолируется и баги уйдут)))


      1. SpiderEkb
        11.06.2023 10:26

        Скорее всего, да. Начали без четкого понимания что будет в оконцовке, прикручивали одну фичу за другой (все что на ум пришло по дороге), дошли до состояния когда оно начало рушится под собственным весом. Пришли к тому, что надо все переписывать. И решили переписать все уже модульно. Обозвали это модным словом "пилим монолит". Но поскольку нормальная организация процесса где есть архитекторы, аналитики - это "фи, энтерпрайз какой-то, у нас тут все молодые-свободные и вообще стартап", то опять ни до чего не договорились, только разосрались, на то все и закончилось.


  1. Dimaasik
    11.06.2023 10:26
    +2

    Вывод напрашивается сам собой - монолит не нужно распиливать, ему нужно поклоняться и желания загадывать)


  1. cat_chi
    11.06.2023 10:26
    +12

    Первые проблемы начались в момент, когда мы начали строить архитектуру. Каждый гнул свою линию и не очень хотел идти на компромисс.
    Максим хотел разбить достаточно простую логику на кучу-кучу микросервисов, где каждый сервис выполнял одну мизерную задачу. Я хотел разбить логику на чуть более большие куски, чтобы каждому досталось не больше двух-трёх сервисов, дабы не сойти с ума. Алексей для внутреннего общения сервисов хотел использовать gRPC, Я и Максим - RestAPI.
    Наш техдир принял решение сбросить всю ответственность с себя тактически отступить и сказал: «делайте как хотите, я ни хрена не понимаю».

    Подозреваю, что "микросервисы" – наименьшая из ваших проблем :) Отсутствие консенсуса по архитектуре, и отсутствие человека, который либо привёл бы всех к консенсусу, либо сказал – "делаем так, потому что я тут главный, ответственность на мне" – вот проблема. На выходе – лебедь, рак и щука.


  1. creker
    11.06.2023 10:26

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

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

    Предварительно менеджер и техдир (и тимлид, раз он тут архитектор главный стал) таки должны были обрисовать план, зачем это бизнесу надо. Какие конкретно метрики это улучшит. Нужно ли реально было все переделывать или достаточно было рефакторинга и подумать немного про архитектуру.

    Ну и конечно же, монолиты, в зависимости конечно от размера, обычно "душат". Отколупливают изолированный функционал в новые сервисы, а новый функционал сразу пишут в отдельных сервисах. Иначе "бэкэнд 2.0" может никогда так и не уйти в продакшен.


    1. Leetc0deMonkey
      11.06.2023 10:26

      Техдир, по сути, должен был выступать тем самым техлидом,

      Техдир технично слился, уже по опыту пятой точкой чувствуя что всё это не нужно. Зачем тратить время и энергию на эти игры?


  1. nronnie
    11.06.2023 10:26

    Я сторонник микросервисов, но, так как они часто реализуются, блин, для тех кто такое делает особое место в аду должно быть. Имеем сейчас типа "микросервисный" проект, где мало того, что все засунуто в одну монорепу, так еще все вообще засунуто в один солюшен, с зависимостями не через пакеты, как положено, а через <ProjectReference>В результате над всей этой конструкцией даже чихнуть страшно, чтобы она от своей дичайшей связанности не развалилась. Если так делать, то уж пусть лучше будет монолит - хотя бы не будет всех проблем с кучей процессов и их взаимодействием между собой.


    1. SpiderEkb
      11.06.2023 10:26

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

      Но все это требует качественной архитектурной проработки. А делать "микросервисы ради микросервисов" - порочно. Как и любая концептуальность ради концептуальности.

      Где-то микросервис может быть действительно "микро". А где-то это может быть небольшой такой мололитик просто потому что он реализует какой-то один кусок бизнес-логики, который нет смысла дробить дальше (хотя бы потому, что это порождает лишние зависимости).


  1. MVS366
    11.06.2023 10:26
    +2

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

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


  1. Ilya_Romashev
    11.06.2023 10:26

    Лол, у юджина и других проблем навалом, распил монолитов не самая большая.