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

Если вспомнить, то идея модульных микросервисов всплыла около десяти лет назад на подъёме идеологий гибкой разработки (Agile) и DevOps. Эти мощные концепции сильно повлияли на индустрию.

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

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

Монолит (монолитное приложение) — одноуровневое, самодостаточное и независимое приложение, которое не ставит модульность компонентов в основу разработки.
Поскольку монолитные приложения всегда разрабатываются в монорепозиториях, то происходит некоторая путаница в понятиях. В общем, если упростить:

  • Монолиты — всегда монорепозитории.
  • Монорепозитории — не всегда монолиты. Внутри монорепо могут жить и развиваться множество независимых модулей, которые по определённым причинам не выносят в отдельные репозитории (например, большим корпорациям так удобнее), вроде такого:

    .
    ├── README.md
    ├── lerna.json
    ├── package.json
    ├── packages
    │   ├── cli
    │   ├── component-button
    │   ├── eslint-config
    │   ├── generic-box-sizing-reset
    │   ├── object-aspect-ratio
    │   ├── object-container
    │   ├── object-grid
    │   ├── ...
    │   └── utility-width
    └── test
        ├── ...
        └── test.sh

Достоинства монорепозиториев:

  • Единый источник истины. Изменения кода атомарны, нет необходимости синхронизировать схемы в нескольких репозиториях.
  • Видимая стоимость изменений. Внесение изменений в код требует совместимости со всем остальным кодом.
  • Совместное и повторное использование кода. Значительно проще находить нужный код повторно использовать существующие компоненты. Это также включает версионирование и согласование зависимостей в рамках всей организации.
  • Буст сотрудничества. Исчезает бюрократия с разрешениями и согласованием нескольких репозиториев. Просто изменяем код и получаем отзывы!

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

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

▍ Простой монолит — это хорошо


Сторонники монолитов неоднократно подчёркивают, что их выбор обусловлен простотой. То есть простая архитектура приложения, простая разработка по классике — это идеальный вариант. Особенно в начале стартапа. Монолит — это простая архитектура, которая решает проблемы простым способом. О преимуществах монолита говорит Дэн Лу (Dan Luu), технический директор команды из 70-ти инженеров, разработавших платёжное приложение Wave:


Среди больших, но эффективных монолитов называют StackOverflow (входит в топ-100 сайтов интернета), Slack (почти PHP-монолит), Booking, GitHub, Shopify, Stripe (монолит, распределённый в подах k8) и многие другие. Это успешные продукты с точки зрения бизнеса — стоимостью более миллиарда долларов. С точки зрения эффективности или производительности могут быть вопросы, но это уже субъективные вещи. Всё-таки стоимость бизнеса — некий объективный численный показатель, который должен коррелировать с пониманием успешной софтверной разработки.

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

То есть простой монолит — вполне достаточный продукт в большинстве ситуаций. В то же время на конференциях и в СМИ этот простой и скучный тезис редко становится темой обсуждения. Ведущие инженеры и специалисты любят разбирать распределённые архитектуры из микросервисов, балансировку нагрузки по кластерам и другие сложные вещи. Чем сложнее архитектура — тем круче доклад. Банальные простые вещи не очень подходят для презентации, хотя это 99% задач в реальном мире.

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

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

▍ Микросервисы в реальной жизни


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

Представим, что Netflix использует микросервисную архитектуру. Как будет выглядеть эта воображаемая инфраструктура в самом упрощённом виде? Примерно так:



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

▍ Сложные системы быстрее падают


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

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

В физике чем сложнее система — тем выше диссипация (рассеяние) энергии, то есть выше скорость деградации этой системы. Отсюда можно сделать вывод, что сложные системы быстрее падают.

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

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


«EKS отменяется в конце месяца для Omega Star, но Omega Star по-прежнему не поддерживает таймстампы ISO...» Из вирусного видео «Микросервисы»

Есть ещё другое следствие. Чем сложнее система — тем больше энергии требуется на поддержание её состояния. То есть в контексте программных систем это означает стоимость поддержки и обслуживания. Более простые системы легче обслуживать. В идеале простой монолит на Node/Express без критичных зависимостей годами спокойно работает — и не требует особого обслуживания.

То же самое можно сказать и о простом наборе микросервисов, который заменяет сложный монолит. Главное здесь — в каком направлении мы двигаемся, увеличиваем сложность или упрощаем систему?

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

Одна лишняя, ненужная деталь в начале проекта тянет за собой впоследствии сотни человеко-часов избыточной работы. Это как в жизни — любая ненужная вещь отнимает ваше внимание на протяжении её присутствия рядом. Поэтому ради оптимизации времени желательно изначально не плодить сущностей.

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

▍ Монолиты — наш друг


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

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


  1. vagon333
    18.07.2022 14:03
    +12

    Не могу согласиться или возразить.
    Каждой задаче своя архитектура.
    Иногда, весь бизнес компании - набор API сервисов. Тут выбор архитектуры очевиден.
    Иногда, нужен софт для работы ... лесопилки. Простой, как табуретка. Выбор тоже прост.
    It depends.


    1. napa3um
      19.07.2022 11:40
      +1

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

      Да, всё зависит от всего, а статья - про некоторые суеверия и приметы, которые помогают осуществить этот выбор :).


  1. ValeryGL
    18.07.2022 14:30
    +10

    С удовольствием прочитал.

    Увы, больше тезисов, чем доводов. "Микросервисы - система сложная, энтропия, значит - ненадежная; а монолит простой, маленький, красивый"; если авторизация в Спотифае вынесена в отдельный сервис - она собой завалит всё; а если она часть монолита - то может падать безболезненно.

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


  1. Karchevskiy
    18.07.2022 14:38
    +9

    Монолиты — всегда монорепозитории

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


  1. des1roer
    18.07.2022 14:56
    +6

    Монолиты они больше про технический долг. Если писать тесты, следовать SOLID, применять code style фиксеры, использовать ci, то оно может быть нормальным довольно долго. Но со временем кодовая база растет, хотелки растут, число разрабов растет. И вот уже тесты проходят по 40 минут, каждый деплой - это тьма гит конфликтов, понять что делает система от начала и до конца уже никто в одиночку не способен - тут да приходят микросервисы. И снова можно быстро деплоиться, знать небольшой кусок архитектуры и вообще расти. За счет утилизации времени и процессорных мощностей на уровне интеграции микросервисов - но в целом альтернатива что корректно в огромный монолит новый функционал может и добавить будет нетривиально


    1. SlimShaggy
      18.07.2022 17:19
      +14

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

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


      1. Norgorn
        19.07.2022 09:01
        +2

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


      1. nlog
        19.07.2022 14:53
        +2

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


    1. ris58h
      18.07.2022 19:14

      А просто сервисы не приходят?


    1. WASD1
      18.07.2022 22:53
      +9

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


      1. spacediver
        19.07.2022 11:10

        кусок ада или кусок кода? ;)


        1. KonstantinID
          19.07.2022 14:16

          да


  1. vvovas
    18.07.2022 15:38
    +15

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

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


    1. Lexer11l
      21.07.2022 09:14

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


  1. kovriga25
    18.07.2022 23:25
    +1

    booking не монолит уже много лет


    1. TimsTims
      19.07.2022 12:20
      +1

      уже много лет

      Ключевое слово: "уже". То есть booking вполне себе нормально рос будучи монолитом. А потом, как раскрутился - нанял +100500 разрабов, чтобы разделить всё не микросервисы. Если писать сразу микросервисы, то с самого начала требовалось бы больше времени на допилку и поддержку микросервисов, что кушало бы лишние ресурсы, замедляло разработку. И не факт, что booking выжил бы, если бы всё изначально писал на микросервисах.


  1. RH215
    19.07.2022 00:26
    +3

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


    1. greenkey
      19.07.2022 01:24
      +2

      где та грань, между микро- и просто сервисами?


      1. pfffffffffffff
        19.07.2022 08:36
        -2

        Пример: сервис видео который позволяет загружать новое видео и получать список видео. А в микросервисах для этих двух фич 2 микросервиса.


      1. murenaa
        19.07.2022 14:10

        В сервис-ориентированном приложении каждый сервис отвечает за свой домен. Например сервис доставки, сервис заказов.

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

        Как минимум, это один из критериев.


        1. greenkey
          19.07.2022 17:07

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


          1. murenaa
            19.07.2022 18:10

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

            https://youtu.be/xkr5nGJYx_U


            1. greenkey
              20.07.2022 16:33

              Спасибо, очень интересно


  1. Ekstrem
    19.07.2022 10:43

    За такими заявлениями явно есть свои интересы!!!)
    Отрицать МСА - это как не пользоваться смартфоном, а только городским телефоном проводным.
    Любые сложные системы/подходы/продукты появляются не на ровном месте, не от гения творца, а в ходе длительного развития.
    Смысл MSA в том что описанные сложности решаются системно, для всего ландшафта сразу, что даёт "эффект масштаба", позволяет применять эту архитектуру. При этом, конечно, имею место предпосылки к развитию архитектуры на ландшафте.
    Выбор архитектуры программного обеспечения, как формы его развития, тесно связан с реализуемой функциональностью и окружающими обстоятельствами. По мере количественного роста, с одной стороны, реализованных фичей, и, с другой стороны, количества заинтересованных сторон, в движении этих внутренних и внешних факторов, форма программного обеспечения склонна изменяться, выражаясь в новой архитектуре решения.
    Задача гибкой архитектуры при этом: предвосхитить возможные изменения, производя наиболее адаптируемый к изменениям продукт, приносить заинтересованным сторонам продукт с наиболее высокими потребительскими качествами.
    Воспроизведу подобный материализм развития:

    1. Монолитное приложение - это продукт, состоящий из нескольких слоёв или уровней, которые можно выделить логически, иногда физически:

    • Интерфейс;

    • Логика приложения;

    • Слой доступа к данным;

    • База данных.

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

    • сложность системы постоянно растет;

    • поддерживать ее все сложнее и сложнее;

    • разобраться в ней трудно — особенно если система переходила из поколения в поколение, логика - забывалась, люди уходили и приходили, а комментариев и тестов нет);

    • много ошибок;

    • мало тестов — монолит не разобрать и не протестировать, поэтому обычно есть только UI-тесты, поддержка которых обычно занимает много времени;

    • дорого вносить изменения;

    • застревание на технологиях

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

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


    1. TimsTims
      19.07.2022 12:36

      сложность системы постоянно растет;

      Тоже применимо к микросервисам - их становится много.

      дорого вносить изменения

      На ваш (микро)сервис авторизации подписано 100 внутренних систем. Вы уже не можете внести в неё изменения, без изменения логик 100 других систем.

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

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

      Задача ИТ - соблюдать баланс между скоростью, стоимостью и качеством разработки. Я бы добавил ещё гибкостью. Этот баланс всегда, в любой момент времени разный. На старте продукта тебе нужны mvp , чтобы проверить гипотезу и жизнеспособность продукта (быстро и дёшево). Если он не выстрелил - выбрасываем, не жалко. Если выстреливает - уделяем время на доделку/переделку архитектуры. Если проект прям печатает тебе деньги, и у тебя на носу миллионы-миллиарды, значит ты спокойно можешь нанять ещё +10 разработчиков, которые сделают вторую версию очень качественного продукта хоть на микросервисах с масштабированием, итд.

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


      1. Ekstrem
        19.07.2022 13:31

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

        Интересная мысль про баланс. ИМХО, лиды/архитекторы/owner'ы именно для соблюдения баланса и нужны, именно в движении противоречивых интересов рождаются, выраствют, умирают все продукты)


    1. FetTroll
      19.07.2022 12:41
      +1

      "Отрицать МСА - это как не пользоваться смартфоном, а только городским телефоном проводным." не могу согласиться с таким сравнением. Смартфон - это монолит. А вот если у вас будет экран в одной руке, клавиатура - в другой, а приёмопередатчик  где-то в кармане, и т.д. - это микросервисы. В некоторых случаях это оправдано, в некоторых - нет. Если проводить аналогии, подобные вашей, то микросервисы - это ПДУ от телевизора и сам телевизор. Каждый отвечает за свою задачу, а в итоге пользователеть получает желаемую картинку на экране. Для каждой задачи своё решение.


      1. Ekstrem
        19.07.2022 13:22

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


    1. Ekstrem
      19.07.2022 13:51

      Позволю себе больше, определю эту статью

      1. как агитацию простых решений, которые не требуют больших затрат.

      2. как пропаганду сегрегации ролей в производственном процессе.

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


  1. vvodan
    19.07.2022 14:10

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

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

    При проведении собеседований у меня один из любимых вопросов - назовите плюсы монолита и минусы микросервисов) Очень мало кандидатов могут вдумчиво ответить на этот вопрос)


  1. Hellpain
    19.07.2022 16:49

    Статья как бальзам на душу. Примеров разумной микросервисной архитектуру очень мало.


  1. XaBoK
    19.07.2022 17:16

    Если взять аналогию со строительством, то можно заметить, что на лицо подмена (скорее всего не осознаная) понятий архитектуры, стиля, материала и назначения. Строя дом вы придёте к архитектору и не может быть, что диалог у вас будет из одного слова. Типа Баухаус или Брутализм. Скорее всего у вас будет что то типа: "классический дачный домик из дерева", но и этого мало. Вы начнёте обсуждать избушку ли вам строить или скандинавский вариант, и как вы планируете его использовать. Но почему то в ИТ все считают, что можно просто сказать "микросервисы" и это будет ответ на главный вопрос жизни, вселенной и всего такого.