Введение
День добрый, господа хорошие. На данный момент я в IT уже порядка 15 лет. Большую часть времени я был разработчиком, и даже уход в ветку менеджмента скорее дал толчок к работе над личными пет-проектами, чем к отказу от разработки.
За эти 15 лет было интересно наблюдать за изменением трендов, особенно вне энтерпрайз разработки. Самое интересное — это наблюдать, как технологии и паттерны циклически развиваются.
Парадокс сложной эффективности
Сегодня я хочу обсудить «Парадокс сложной эффективности». Давайте начнём с наглядного примера в игровой индустрии. Как многие из нас знают, в онлайн-играх есть система адаптивного баланса. Например, если какая-то техника слишком хорошо проявляет себя в игре, её боевой рейтинг повышается, и она будет сталкиваться с более сильной техникой.
Но есть нюанс: техника может быть мощной и сложной в использовании. Если в команде есть игрок, который умеет ей пользоваться, команда выигрывает с вероятностью 99%. Все знают это и пытаются играть на ней, но большинство не понимает, как это делать правильно, из-за чего техника не растёт в рейтинге, и триггер адаптивного баланса не срабатывает. В итоге, техника имеет плохой баланс и не приносит пользы большинству. Вот и пример «Парадокса сложной эффективности».
Применение в IT
Как это относится к текущим реалиям софтверной разработки? Рассмотрим многопоточность и производительность. Когда я начинал заниматься разработкой, многопоточность была чем-то сложным и не прощающим ошибок. Те, кто умел эффективно её использовать, писали отличные приложения, остальные тратили кучу времени на исправление дедлоков и утечек памяти. Приложения были эффективными, но их разработка занимала много времени и была дорогой.
Создатели языков начали добавлять синтаксический сахар, чтобы упростить работу и уменьшить вероятность ошибок. Работал ли этот код в многопоточном режиме? Ну в целом да, так же быстро. Но есть нюанс. Сахара становилось всё больше, и «ну в целом да» работало относительно предыдущего сахара, а вот относительно начала скорее нет.
Помните чудесный и прекрасный MVC, разработанный Xerox в 1979 году? А N-Tier из 90-х годов и Onion Architecture начала 2000-х?
Эти технологии решали проблемы своего времени. Они предлагали инструментарий для решения проблем. Если кто-то скажет вам, что они простые – киньте в него камнем. С ростом проекта всегда становилось сложнее разделять слои, приходилось вспоминать паттерны и думать над организацией кода. Ожидаемо что очень много проектов начали скатываться в «спагетти-код» и иже с ним.
Что с этим делать? Правильно, давайте перейдём на новый уровень витка. Просто разрежем это на мелкие приложения и сделаем кучу микросервисов. И что мы слышим? Да, крики общественности такие как «Долой все эти MVC, N-Tier!», «Зачем мне многослойка для CRUD API, работающего с одним ресурсом?».
Хорошо, хотите микросервисы – получайте новый набор инструментов:
API Gateway, Saga, Circuit Breaker
Bounded Context, Decompose by Business Capability, Decompose by Subdomain
Consolidate by Ownership, Merge by Functionality, Aggregate by Usage
В своё время мне очень понравилась фраза Мартина Фаулера, которая в моих кругах общения почему-то не обрела популярности.
While I do accept that there are valid reasons to go for a distributed design for many systems, I do think distribution is a complexity booster. A coarser-grained API is more awkward than a fine-grained one. You need to decide what you are going to do about failure of remote calls, and the consequences to consistency and availability. Even if you minimize remote calls through your protocol design, you still have to think more about performance issues around them.
Заключение
Что мы получили в итоге:
Проекты, в которых количество микросервисов перевалило за тысячу штук.
Проекты, в которых чек за логирование и трейсы стоит больше, чем вся остальная инфраструктура.
Проекты, в которых Cold Start однопоточных FaaS решений дольше, чем время выполнения кода.
Что мы слышим в общественности? Всё довольно ожидаемо:
Да здравствуют монолиты!
Даёшь хардкорный Си!
Даёшь Rust!
Почему так происходит? Потому что мы выбираем технологию, в которой кто-то успешен. Когда не выходит, говорим, что она устарела и переходим к следующей успешной технологии. Это и есть циклический «Парадокс сложной эффективности». Как говорится в басне Крылова:
«Тьфу пропасть! — говорит она, — и тот дурак,
Кто слушает людских всех врак;
Всё про Очки лишь мне налгали;
А проку на-волос нет в них».
...
К несчастью, то ж бывает у людей:
Как ни полезна вещь, — цены не зная ей,
Невежда про неё свой толк все к худу клонит;
А ежели невежда познатней,
Так он её ещё и гонит.
Итак, когда вы собираетесь сказать, что какой-то инструмент плох, и готовы кричать об этом, может быть, вы его не к тому или не так прикладываете? =)
Дополнительные референсы:
Martin Fowler о микросервисах: martinfowler.com
Многослойная архитектура: Wikipedia
Луковая архитектура: Jeffrey Palermo's blog
История MVC: Wikipedia
Комментарии (14)
saboteur_kiev
21.06.2024 22:27Проекты, в которых чек за логирование и трейсы стоит больше, чем вся остальная инфраструктура.
А еще мониторинг.
Сейчас очень популярен прометеус, но даже не половина, а 90% разработчиков понятия не имеют что в нем есть, и тупо кидают туда все подряд. Пользуясь максимум 5-10% метрик. А метрики эти надо собирать, хранить, надо возможно бэкапить, надо возможно даунсамплить. Возможно настраивать какие-то дашборды в прометеусе или графане. А их никто не смотрит, а еще возможно надо какой-то меш, чтобы не потерялись все эти микросервисы...
В то время как более простые варинаты мониторинга с ручной подкруткой требуют в разы меньше ресурсов.. Но их нужно сетапить, а прометеус говорит что "я все за вас сделаю"...opusmode
21.06.2024 22:27Да и правильно говорит. И даже хорошо, что разрабы туда научились кидать.
И даже борды не надо смотреть, просто потому, что это тупо.
Задача таких инструментов, это централизованный сбор и обработка метрик. В одном случае для алёртов, в другом для ручного анализа проблем
saipr
21.06.2024 22:27+2Справедливо:
вы собираетесь сказать, что какой-то инструмент плох, и готовы кричать
об этом, может быть, вы его не к тому или не так прикладываете? =)Здесь бы я всплмнил необоснованную критику Ричардом Столлманом языка tcl/tk и слова Брайана Кернигана:
Удачным кажется и то, что разделение задач между Тсl и С/С++
осуществляется достаточно легко, надо только знать, какой инструмент
лучше справляется с задачей...
Octabun
21.06.2024 22:27+2В своё время мне очень понравилась фраза Мартина Фаулера,
Которая оказалось не фразой а высказыванием. А так, аналогично анекдоту о молчащем мальчике, всё в замке нормально.
Я бы добавил, что механика динамики трендов двухфазная. Сначала у менеджмента возникает новая идея как сэкономить, а потом её копируют окружающе. Таким образом, мы имеем именно мартышку в квадрате.
Правильно относиться к феномену, то есть не ждать от гоминид иного вообще, может помочь, например, популяризаторская деятельность профессора Савельева, что на YouTube что через книги.
amazingname
21.06.2024 22:27+6Никогда не думал что микросервисы можно рассматривать как средство борьбы со сложностью. Монолит проще всегда, а все архитектурыне преимущества декомпозиции в 10 раз проще реализовать внутри монолита абстрактно чем порезав систему физически на куски.
Преимущества микросервисов - независимый деплой и независимо работающие команды. По-моему только так отвечают даже на собесах.
Например, надо добавить новую фитчу. В монолите при этом может потребоваться несколько сквозных доработок на всех уровнях, начиная с одной на всех модели базы данных. В итоге нужно вовлечь много людей, кто-то занят, придется ждать.
Если же архитектура микросервисная - как правило команда ответственная за фитчу пилит и деплоит ее а другие команды даже ничего не знают. Это реально работает. Плата за такую архитекруру - адово нарушение DRY (нет крутой наработанной за годы платформы на все случаи жизни, каждая команда пилит ее элементы сама) и куча трудностей с агрегацией/синхронизацией данных из разных сервисов.
opusmode
21.06.2024 22:27Микросервисы проще всегда, просто потому, что вы работаете с меньшим количеством кода и пилите конкретный проект, а с другим сервисом общаетесь через gateway.
Потому, очевидно, вам не надо разбираться, какая часть кода про этот функционал, а какая нет. Не надо раздумывать, не натворит-ли ваша фича что-то в другом функционале.
Так что единственное, что в монолите проще, это наговнокодить и поруинить всё, а вот разбираться с рукотворным памятником тараканам из головы конкретного разработчика, вот это куда сложнее, чем в микросервисах.
так что монолит это хорошо до определённого момента, пока есть ядро функционала. Когда фичи разбухают, есть смысл их выносить. Ну, прям как деление клетки
amazingname
21.06.2024 22:27+5Микросервисы проще всегда, просто потому, что вы работаете с меньшим количеством кода и пилите конкретный проект, а с другим сервисом общаетесь через gateway.
Хм.. Не согласен. Был свидетелем частичного перехода продукта на 10 млин строк кода с монолита на микросервисы. Такое как вы пишете впечатление может создаться у человека который две недели в проекте, или если в этом монолите забили на любую архитектуру и затыкали дыры кто во что горазд. Но если монолит работоспособен и конкурентен, то обычно это означает что его проектировали далеко не дураки. В нем всегда будет совершенно ясное разделение на модули, слои, будут красивые эффективные концепции. Причем все это будет сделано лучше чем в микросервисах из за отсутствия дополнительных ограничений.
Если эта архитектура не выработана, то очень наивно надеятся, что просто выбор микросервисной архитектуры эту архитектуру внесет. Если компания не смогла нанять людей, которые могли бы сделать красивый монолит, она тем более не сможет сделать вменяемую микросервисную архитектуру.
В сущности микросервисную архитектуру со всеми ее концепциями примерно раз в 10 проще один в один воспроизвесити в монолите, чем в ее натуральном виде. Просто API сервисов превратятся в интерфейсы.
Если вам нужно добавить новую фитчу, в монолите вы попадаете в обсустроенный мир, где все уже предусмотрено, надо только посмотреть что он вам предоставляет и добавить свой код. В микросервисах конечно тоже подобное можно реализовать, но тогда это будет опять тот же монолит, только раз в 100 более медленный.
Суть микросервисов, как раз в том чтобы в каждом сервисе было намного больше кода чем нужно, что вам придется делать самостоятельно много вещей которые в монолите уже были бы из коробки. И соответственно придется иметь дело с большим количеством плохого кода чем в случае монолита. Но зато теперь команда может добавить в базу сущность или использовать любимый фреймворк не спрашивая главного архитектора компании. И не нужно идти на поклон к ведущему девелоперу, чтобы добавить мелкую фишку в платформу, потому что удобной и гибкой платформы больше никакой нет, а вместо нее локальный кривоватый кусочек кода, воспроизводящий то что было в платфонме в частном случае. Оно хуже чем было в платформе монолита, но зато ваше персональное решение, которое можно менять хоть каждый спринт.
Потому, очевидно, вам не надо разбираться, какая часть кода про этот функционал, а какая нет. Не надо раздумывать, не натворит-ли ваша фича что-то в другом функционале.
Ну нет, так не бывает. Я такого во всяком случае ни разу не видел. Так бывает если позволить рулить в проекте программистом с двумя годами опыта. Проблема когда у вас одна фитча ломает другие преодолевается любым девелопером после того как он запустил свои первые 30 000 строк кода. Если люди этого не умеют и вы поручите им проектировать микросервисную архитектуру, то результат буде точно таким же - непостижимо запутанная сеть микросервисов вместо непостижимого монолита.
Так что единственное, что в монолите проще, это наговнокодить и поруинить всё, а вот разбираться с рукотворным памятником тараканам из головы конкретного разработчика, вот это куда сложнее, чем в микросервисах.
Так в микросервисе как раз разработчик чувствует себя гораздо свободнее в плане говнокода. И потом с ним все равно придется разбираться.
Могу повториться, по моему мнению это очень наивная надежда. Если люди не умеют строить архитектуру в монолите (это относительно простой навык) и вы просто добавите им искуственные заборы, все станет только хуже, потому что работа с заборами требует больших навыков, чем без них.
Это примерно как задолбаться с процедурным говнокодом и заставить людей пользовать ООП и надеяться что теперь все станет лучше. Никогда в жизни не станет. Люди которые не научились писать понятный процедурный код точно не смогут написать понятный объектный.
так что монолит это хорошо до определённого момента, пока есть ядро функционала. Когда фичи разбухают, есть смысл их выносить. Ну, прям как деление клетки
Да, это совершенно верно. Но проблема не в запутанности монолита или говнокоде в нем. Проблема в том что монолит это идеальная архитектура для сольного разработчика, который в одиночку пилит весь проект. В случае если проект пилит 100 человек, возникют те самые проблемы о которых я писал. Вам нужно добавить фитчу, для этого нужно что-то поменять том самом удобном и универсальном окружении монолита, которое вы используете. И для этого становитесь в очередь к ведущему разработчику компании, чтобы он это сделал или согласовал, а потом ваш клиент будет ждать пол года пока будет очередной деплой монстра. С микросервисами пишем все самостоятельно, пусть кривее, пусть еще две команды делали почти то же самое, но зато прямо сегодня, отвечает за это конкретная команда и никто ей больше не нужен. И продукт идет вперед.
indestructable
21.06.2024 22:27Микросервисы проще всегда, просто потому, что вы работаете с меньшим количеством кода и пилите конкретный проект, а с другим сервисом общаетесь через gateway.
Для этого необязательно физически разделять микросервисы, можно разделить на модули, как физические (отдельные библиотеки), так и, условно, на папки в репозитории.
LaRN
21.06.2024 22:27+1Это работает пока не нужно пилить фичу, которая аффектит больше чем на одну команду, а таких фич довольно много. И как только такое случается проблем возникает сильно больше, чем если бы делали в модульном монолите, т.к. командам нужно взаимодействовать и нужен кто-то, кого будут все слушать в спорных ситуациях.
Batalmv
21.06.2024 22:27+2Дело не в цикличности, а в том, что новое не заменяе старое, а сосуществует с ним. Почти всегда. Другое дело, что есть тренды и им обычно следуют в большинстве случаев
Что касается проблем - так они почти все от ДНК, а он не меняется
opusmode
21.06.2024 22:27+3Вот, кстати, согласен. Кажется основное, что плохо понимают люди, это то, что «одно другому не мешает». А людям надо постоянно всё друг другу противопоставить и обязательно занять сторону, а потом с пеной у рта доказывать, что их херня лучше, чем херня соседа.
Хотя практика показывает, что именно разнообразие подходов и грамотное их сочетание даёт отличный рост, что не надо пытаться решать все задачи одним, самым правильным способом
rukhi7
21.06.2024 22:27Крылов писал так-сказать-микросервисы в виде басен, а Пушкин писал и так-сказать-микросервисы в виде стихов, и так-сказать-монолиты в виде например "Евгений Онегин". Вопрос: кто был-есть более успешен?
Vasjen
Звучит как очень краткий пересказ сказки. Однажды, давным-давно, в тридевятом царстве, в превеликом государстве жил был дед. И вот, однажды, по усам текло, а в рот не попало.
Микросервисы появились не из-за проблем с многослойкой или нежеланием разделять, это не аналог или замена MVC. Как сравнивать теплое и мягкое, в общем.
Монолиты никогда не был злом, им пугали менеджмент, что вот если оставим все как есть, то стоимость сопровождения и внедрения новых фич будет расти экспоненциально. У кого-то это было оправдано, кто-то выбивал / пилил бюджеты, кто-то хотел, потому что модно и нужно для резюме.
opusmode
Монолиты никогда не был злом, им пугали менеджмент, что вот если оставим все как есть, то стоимость сопровождения и внедрения новых фич будет расти экспоненциально. У кого-то это было оправдано, кто-то выбивал / пилил бюджеты, кто-то хотел, потому что модно и нужно для резюме.
Поздравляю, вы кратко пересказали статью и её посыл