Комментарии 86
Никакой DDD и прочие заумные практики разработчикам уже не нужны (микросервисы и так обеспечивают bounded contexts)
Мне казалось, что DDD это несколько больше, чем просто физическое разнесение архитектуры по сервисам.
Если рассматривать код микросервиса, то дефакто всё DDD вырождается к правильному наименованию. Всё остальное идет на уровне архитектуры взаимодействия микросервисов и распределения их по командам.
Правило думали.
Никакой DDD и прочие заумные практики разработчикам уже не нужны (микросервисы и так обеспечивают bounded contexts)
Микросервисы это обеспечивают как раз потому, что есть такие «заумные» практики как DDD. Которые и помогают понять, как разделить предметную область на подобласти, а их уже на сервисы.
Я имею в виду, что в случае микросервисов разделение предметной области на подобласти больше не делается в коде, а продумывается на уровень выше. И это делается более явно, и это проще, чем поддерживать дисциплину в коде одного приложения, чтобы разделять там логику на части.
Т.е. наличие микросервисов - это и есть DDD
Верно, так и должно быть. Сначала идёт проектирование (DDD), а потом уже код.
Возможно, ошибочно сложилось впечатление, что от Вас посыл был несколько в обратном, что DDD не нужен. Хотя такая методология как раз и дает ответы на вопросы. Чтобы потом не приходилось переписывать код множество раз.
Ну всегда можно сказать, что Windows или Linux это просто один большой микросервис, а не монолит)
Если отдельный модули исполняются на разных машинах, то это, по определению, уже не монолит. Монолит это именно что огромный клубок кода, который компилится хер знает сколько. Это все естественно разбито на модули, библиотеки. Используются билд кэши и прочие оптимизации, чтобы инкрементальный билд в большинстве случаев эту проблему сгладил, если у нас компилируемый язык какой-то. Но по итогу это все равно огромная пачка бинарей, которая деплоится и запускается целиком на одной машине.
Разработка именно что отличается кардинально между этими подходами. Именно по этой причине во многом микросервисы рождаются из масштабов не только приложения, но и команды.
Так что это у вас скорее какие-то странные понятия монолита и микросервисов.
>Компилится хер знает сколько
Меня вот, если честно, всегда это веселит. Компилятор, вообще, за нас делает кучу работы по проверке кода. Эту работу, при растаскивании монолита на микросервисы часто, в итоге, приходится делать каждый раз "руками" (в смысле головой), о чем, как правило, на этапе растаскивания никто не думает - волшебное слово "микросервис" оно ведь даже лучше чем "пожалуйста", все контракты после этого начинают соблюдаться автоматически :)
Это классика. Людей бомбит вообще от всего, чего они не понимают, понимают не так, если внедрялось или использовалось неправильно, или в условиях, где это вообще было неуместно.
При чём это две стороны одной медали. Сначала совершенно безумный хайп. Микросервисы наше всё! Затем не менее безумный хейт: насмехательства, шутеечки, типа "волшебный микросервис, ха-ха".
Я считаю, что в обоих лагерях нет инженеров, так как инженер смотрит на всё прагматично. А не по-детски дует губу, что "волшебный микросервис" внезапно не порешал все проблемы и болячки, и не устранил сложность в разработке.
Разница вроде бы довольно очевидна. Чтобы обновить монолит надо обновить какой-то бинарник на всех инстансах. Чтобы обновить микросервис надо обновить один сервис. Это помимо возможных потенциальных плюшек в виде более простой масштабируемости и отказоустойчивости.
Да и для начала хорошо бы определится, что такое "монолит", а то так можно любой дистрибутив линуха монолитом назвать. Вот вам и ядро монолитное, и процессы разные, но они ведь тоже на принципах модульной разработки и разделения ответственности основаны, значит и это все "монолит".
Опять же если не считать все "монолитом", то самая разумная аналогия, это когда мы считаем, что механизмы межпроцессного взаимодействий(IPC) ОС внутри одного инстанса, заменены на сетевые.
А если не бинарник? Если это скриптовый монолит, и для его обновления надо править скрипты на всех инстансах? А если не скрипты, а конфиги?
Как и во всем в этом мире, грань между "монолитом" и "микросервисами" размыта. И любой проект при поспешном росте (а другого сейчас нет) сваливается в эту серую зону, где вроде бы и модули/сервисы разделены, и архитектура описана, и ответственности между командами поделены, но иногда надо поправить что-то во всех инстансах.
Чтобы обновить монолит надо обновить какой-то бинарник на всех инстансах. Чтобы обновить микросервис надо обновить один сервис.
Чтобы обновить монолит, надо обновить один бинарник на всех серверах где он крутится. Чтобы обновить микросервис, надо обновить один бинарник на всех серверах, где он крутится. Да ваш микросервис - монолит!
А если этот модуль — сетевая СУБД? Десктопный клиент на Делфи значит уже не монолит?
Получается, что нет, а просто "клиент" в клиент-серверной архитектуре. И мы можем как выкатить новую версию клиента, не трогая сервер БД, так и обновить сервер, не трогая тысячи клиентов.
Одно из главных недостатков микросервисов - это крайне неудачное название и отсутствие чёткого научного определения термина.
Мне кажется логично определить так: микросервис - это сервис, который "владеет" одним или нескольким хранилищем и является единственной точкой входа к этому хранилищу. То есть в БД никто кроме этого сервиса не лезет.
Отсюда очевидны как недостатки (проблема с производительностью и консистентностью), так и преимущества (возможность кэширования и обновление БД без оглядки на другие команды) данной архитектуры.
миксросервису не обязательно ходить в базу. Он может работать с другими сервисами, в том числе и "внешними", как адаптер или мультиплексор
Проблем с производительностью и консистентностью у микросервисов не больше, чем в монолитах, а даже меньше. Просто потому, что микросервис по определению масштабируемое и независимое приложение. Со всеми вытекающими требованиями при разработке.
В монолите зачастую, когда дело доходит до масштабирования, интеграции с другими системами, проблемы вылазят наружу ровно тогда, когда бизнес к этому совершенно не готов.
Определение очень простое. Это отдельное приложение, которое делает одну задачу, и делает её максимально хорошо. При чём в основе этого определения лежит главный козырь: если технология не подходит для решения задачи, можно выбрать другую. Для монолита это невозможно.
Производительность - это прежде всего эффективное использование ресурсов, быстрые алгоритмы и правильные библиотеки.
И только во вторую или даже третью очередь - это масштабируемость.
По-умолчанию, микросервисы производительность ухудшают
Если вы не знаете, как масштабировать макросервисы, то это не проблема монолита. То же самое про интеграцию.
Проблем с ..... консистентностью у микросервисов .... даже меньше
.......что микросервис по определению .... независимое приложение
Сами себе противоречите
В монолите зачастую, когда дело доходит до масштабирования, интеграции с другими системами, проблемы вылазят наружу ровно тогда, когда бизнес к этому совершенно не готов.
Это не проблема архитектуры
Для монолита это невозможно.
Что невозможно, почему невозможно?
По-умолчанию, микросервисы производительность ухудшают
Не согласен. Как раз ровно наоборот.
Если вы не знаете, как масштабировать макросервисы, то это не проблема монолита. То же самое про интеграцию.
Это именно проблема монолита.
Что невозможно, почему невозможно?
Невозможно в монолите использовать любые подходящие для задач технологии. Монолит ограничен только тем технологическим стеком, который в нём используется.
Не согласен. Как раз ровно наоборот.
Берем микросервис против модульного монолита. Точно обмен теми же вызовами через сеть это однозначно быстрее чем работа через память в одном потоке?
Нет конечно, обмен данными по сети существенно медленнее, чем в рамках одного процесса.
Однако, есть много НО:
Но, слишком интенсивный обмен со значительными потерями говорит о неправильном разделении контекстов.
Производительный быстрый обмен всё же возможен (gRPC например)
Именно за счёт микросервисной архитектуры становится возможным эффективно распределить нагрузку на сервисы. Допустим, поисковый сервис требует много памяти, но не требователен к CPU, можно дать ему соответствующие ресурсы, ещё и настроить шардинг. С другой стороны, если требуются именно вычислительные ресурсы, но немного памяти, легко это обеспечить именно там, где нужно. Монолиту придётся дать всё по максимуму во всех направлениях.
Не каждый технологический стек или фреймворк в принципе способен эксплуатировать "работать через память в одном потоке" (например, PHP).
Возвращаясь к производительности. Некоторые части системы могут быть весьма и весьма чувствительны к безопасности, находиться под 10 замками, за фаерволлами, WAF и прочими ИБ-шными штуками. Монолит придётся весь с потрохами посадить на цепь, в ущерб любой производительности. С микросервисами, отсаживаем чувствительный кусок под замок, остальное распределяем по ландшафту максимально оптимальным способом.
Список можно продолжать и продолжать.
Самое интересное наблюдение. Почти что любой разработчик, который работает сугубо на одном проекте, у которого с начала рабочего дня открывается один проект и он в нём работает -- будет до посинения защищать монолиты.
Если компания -- это компания построена вокруг одного единственного программного небольшого продукта, тут просто нет даже возможности выйти за рамка монолита мысленно. Это неудобно. Это неприятно. Это вообще, зачем?
И будут даже правы.
Производительный быстрый обмен всё же возможен (gRPC например)
Физику не обманешь. Вас ограничивает скорость света. Кроме того, данные требуется сериализовать и десериализовать.
Допустим, поисковый сервис требует много памяти, но не требователен к CPU, можно дать ему соответствующие ресурсы, ещё и настроить шардинг
В принципе валидный пример, но это означает что мы гоняем большие потоки данных между серверами, что является сомнительным решением.
А вот как выбор архитектуры влияет на использование шардинга - мне вообще непонятно.
Монолит придётся весь с потрохами посадить на цепь, в ущерб любой производительности
Абсурдное утверждение. Как секьюрность влияет на производительность? И, надеюсь, вы не будете утверждать что монолит нельзя защитить
Монолит ограничен только тем технологическим стеком, который в нём используется.
Чушь. Ничто не мешает написать кусок на котлине, часть на джаве, часть на C++, кусок на Rust-e и слинковать всё вместе в один монолит
И будут даже правы.
Разработчики вообще всегда правы, когда речь идёт о выборе технического решения. На то они и разработчики.
Физику не обманешь. Вас ограничивает скорость света. Кроме того, данные требуется сериализовать и десериализовать.
Никто не собирается обманывать физику. Сетевое взаимодействие далеко не самое частое узкое место.
Может нам и от СУБД отказаться, от всех видов распределённых кешей тогда? :) Там тоже сетевое взаимодействие и сериализация/десериализация. Вообще, претензия на скорость сетевого взаимодействия в отношении микросервисов самая незначительная, но удивительно часто звучит от ярых адептов монолитов. Как аргумент последней надежды :)
В принципе валидный пример, но это означает что мы гоняем большие потоки данных между серверами, что является сомнительным решением.
А вот как выбор архитектуры влияет на использование шардинга - мне вообще непонятно.
Потоки между серверами будут гоняться так или иначе. Как минимум пользовательское взаимодействие -- сетевое с очень длинным путём обслуживания, и не имеет значения как быстро байты перекидываются внутри приложения, если оно не медленнее самой медленной операции.
Шардировать микросервис значительно проще, на порядки, чем монолит. Особенно если не каждый модуль требует этого шардирования, а разные модули требуют совершенно разных стратегий балансировки и масштабирования. Монолит всех подгоняет под одну гребёнку.
Если это не очевидно, то это весьма странно :)
Абсурдное утверждение. Как секьюрность влияет на производительность? И, надеюсь, вы не будете утверждать что монолит нельзя защитить
Я про производительность разработки. Это напрямую относится к теме статьи: time to market. Монолит можно защитить, но защищать придётся сразу всё с потрохами, что надо и что не надо. А значит, в компании с серьёзным вниманием к безопасности, любые значимые изменение это не только тестирование, но ещё и аудит.
Например, микросервисы, реализующие финансовые функции, обработку перс данных могут быть защищены соответствующие рискам и функциям профилями. А какой-нибудь чат, уведомления, каталог услуг/товаров не требует усиленной защиты, можно быстро разрабатывать, быстро деплоить, и не воевать с ИБ.
Чушь. Ничто не мешает написать кусок на котлине, часть на джаве, часть на C++, кусок на Rust-e и слинковать всё вместе в один монолит
А ну да, точно. Какой весёлый монолит получается :) То-то разработчики C++ обрадуются перспективе уживаться с Rust-ом, Go, JS и Kotlin/Java в одном проекте и одном адресном пространстве. Просто мечта!
Разработчики вообще всегда правы, когда речь идёт о выборе технического решения. На то они и разработчики.
Если вы пришли на монолит, у вас уже нет выбора технического решения. Как-то так. Ну и привычный уютный проект, какой мидл откажется выйти за рамки комфорта.
Может нам и от СУБД отказаться, от всех видов распределённых кешей тогда? :) Там тоже сетевое взаимодействие и сериализация/десериализация.
Конечно, встраиваемые БД потенциально быстрее.
Более того, как раз в микросервисах встраиваемые БД особо полезны.
Распределённые кэши - это настолько специфичная штука, что она вам вряд ли пригодится. Если вы их используете, то должны всегда отдавать себе отчёт - зачем.
Вообще, претензия на скорость сетевого взаимодействия в отношении микросервисов самая незначительная, но удивительно часто звучит от ярых адептов монолитов
Это потому что они сталкивались с этой проблемой, а вы ещё нет.
А ну да, точно. Какой весёлый монолит получается :) То-то разработчики C++ обрадуются перспективе уживаться с Rust-ом, Go, JS и Kotlin/Java в одном проекте и одном адресном пространстве. Просто мечта!
Странный вы какой-то. То вам в кровь из носа нужна гетерогенность, то жалуетесь на неё. Вы не поверите, но большинство программ использует кучу библиотек которые прекрасно уживаются в одном адресном пространстве. Представляете? Чудеса!
Ну и привычный уютный проект, какой мидл откажется выйти за рамки комфорта.
Зачем вообще из него выходить? Если архитектура правильная, спроектирована профессионалами, то разработчику (а также тестеру и админу) действительно очень комфортно. В этом её и ценность. А производительность идёт бонусом
Монолит всех подгоняет под одну гребёнку.
Кого он что подгоняет? Вы о чём ? ) Это такой троллинг чтоли??? Прям как из фильма идиократия получается: "нам надо пить воду с электролитами. Зачем? Потому что там электролиты! "
Конечно, встраиваемые БД потенциально быстрее.
С чего бы это вдруг :) Быстрее чего?
Более того, как раз в микросервисах встраиваемые БД особо полезны.
Да не особо.
Распределённые кэши - это настолько специфичная штука, что она вам вряд ли пригодится. Если вы их используете, то должны всегда отдавать себе отчёт - зачем.
Это потому что, вы не сталкивались с задачами, где это нужно. А по факту всё что угодно специфично. Молоток это специфичный инструмент для забивания гвоздей. Шуруп им вывернуть не получится.
Это потому что они сталкивались с этой проблемой, а вы ещё нет.
Я просто не создаю условий, чтобы сталкиваться с этой проблемой. Когда взаимодействие при обработке данных является узким место, решение оформляется в едином процессе. Также есть куча других архитектурных решений.
Нет такой потребности, во что бы то ни стало всё разделять на микросервисы где надо и где не надо, это не самоцель, это лишь одно из средств.
Странный вы какой-то. То вам в кровь из носа нужна гетерогенность, то жалуетесь на неё. Вы не поверите, но большинство программ использует кучу библиотек которые прекрасно уживаются в одном адресном пространстве. Представляете? Чудеса!
При чём тут библиотеки? В микросервисах не используются библиотеки? Как вас понимать? Микросервис это такое же приложение, с библиотеками. Речь про разработку бизнес-функций в полный рост.
Зачем вообще из него выходить? Если архитектура правильная, спроектирована профессионалами, то разработчику (а также тестеру и админу) действительно очень комфортно. В этом её и ценность. А производительность идёт бонусом
Тогда всё ясно. Если разработчику комфортно работать 1 час в неделю, то значит это так правильно, и нечего возражать.
Вообще в любой дискуссии, применение слова "правильный" просто уничтожает любой смысл.
Ведь "правильный монолит" совершенно точно и при любых раскладах будет лучше и кошерней "неправильных микросервисов". А если монолит хоть в чём-то где-то хуже работает чем микросервисная архитектура, то это только потому, что монолит плохой, делали его неправильные пчёлы.
Уж не знаю что тогда вам сказать, только развести руками. Как можно вообще противоречить истинному свидетелю всего правильного и сакральной идеальной архитектуры? Никак.
А по факту всё что угодно специфично
Вот как раз из предложения, что у нас "особый проект", "очень большие данные, аж 100 гигов", "невероятные требования по быстродействию" и берут ноги самые идиотские и кривые архитектуры и решения.
При чём тут библиотеки? В микросервисах не используются библиотеки?
При том, что они написаны на разных языках и прекрасно уживаются, что сводит на нет ваш нелепый аргумент, будто монолит ограничивает технологии и языки.
Тогда всё ясно. Если разработчику комфортно работать 1 час в неделю, то значит это так правильно, и нечего возражать.
Мне вообще кажется, что качество кода обратно пропорционально числу написанных строчек.
Ведь "правильный монолит" совершенно точно и при любых раскладах будет лучше и кошерней "неправильных микросервисов"
Нет, вы просто не понимаете преимуществ и недостатков обоих подходов и находите сложности там где их никогда не было. Особенно доставляет утверждение что микросервисы якобы быстрее.
Современные ОС и так, по сути, микросервисные. Кругом службы, которые переплетены между собой IPC механизмами. Уж какие-нить macOS и iOS точно. Там на mach ports и всяческих надстройках над ними вроде XPC держится буквально все.
Т.е. код-то писать просто, но на проде ему появиться очень сложно.
У меня противоположный опыт. Количество умельцев организовать красивую архитектуру сервиса прям скажем невелико. Поэтому виденные мной монолиты были хрустальными вазами, балансирующими на краю стола. Писать там код нифига не просто. Бывает, что даже либу обновить для фикса CVE - это уже эпик на 2 недели. А уж джаву апнуть с уютной восьмерки - это вообще "давайте в следующем году".
Хорошо, что написали статью. Полностью согласен. Имею опыт и в крупных компаниях с десятками команд и в быстрорастущих стартапах и в совсем молодых. Польностью согласен с мыслями. Сколько стрел и мечей уже было сломано в спорах с бизнесом и коллегами на эту тему.... Про DDD, конечно, жирненько получилось, если не читать комментарии, можно и не понять мысль
Вообще, как по мне, основная мысль здесь вообще не про микросервисы а про следствие одного давно озвученного наблюдения о том, что структура кода очень часто согласуется с организационной структурой проекта. И это не следствие какого-то волшебного и контринтуитивного эффекта - при повторении в коде орг структуры (ну или наоборот, при структурировании организации вокруг кода) проще эффективно организовать работу. Никто не любит тратить время на всякие согласования между подразделениями и, в итоге, модули в коде имеют тенденцию максимально изолироваться, что ускоряет разработку и поставку фич. Само собой, иногда и перегибы случаются и мы получаем странных кентавров с невнятнымы АПИ, но тут ведь не только деление на модули определяется орг структурой, но и наоборот тоже и результат получается вполне сносным.
А что если надо откатить баг, а за это время 100 человек уже написали овердофига нового кода? Что откатывать, что нет? А что если надо выкатить хот фикс, чтобы устранить дыру в безопасности? Сколько это займёт, полдня?
Это больше вопрос конкретно модульности, нежели "микросервисности" как таковой. Микросервисы, это всего лишь один частный способ обеспечивания модульности. Модульное приложение, когда его различные компоненты разрабатываются разными командами, но имеют между собой согласованные и стабильные контракты взаимодействия, в общем случае сопровождаются точно так же относительно легко, как и микросервисы.
Как по мне микросервисы это и есть модульность для вэба. Если бы можно было раскатать все на небольшое количество инстансов, то эту модульность вполне можно обеспечивать другими стандартными средствами. Но если надо раскатывать все на много инстансов, модульность через микросервисы становится просто удобнее и эффективнее.
Как по мне микросервисы это и есть модульность для вэба.
Микросервисы - это очень высокоуровневая модульность. Я вряд ли ошибусь, если скажу, что в даже в большинстве случаев, где есть микросервисы, модульность можно было обеспечивать с намного более тесной связностью модулей и намного меньшим оверхедом.
Но если надо раскатывать все на много инстансов
Понимаете, тут подвох в том, что микросервисы, это не про горизонтальное, а про вертикальное масштабирование. Это вообще лютая подстава с их стороны. Простой пример: вот у вас есть что-то продающий сайт, у него есть микросервис авторизации, есть микросервис просмотра каталога, есть микросервис заказа, есть микросервис оплаты. На вашем очень хорошем сайте стопицот посетителей в день, и у вас на авторизацию ложится стопицот запросов, также стопицот запросов на сервис каталога, и (спасибо воронке продаж) всего лишь пицот на заказы, и сто на оплаты. Вы-то, конечно, можете их по инстансам раскидать, но... у вас любой клиент, прошедший весь путь до оплаты, будет юзать все четыре инстанса последовательно. Вы ничего не выиграете нехило так проиграете по производительности и по пожиранию вашего баланса облачным провайдером в сравнении с монолитом, который запущен в нескольких инстансах, где каждый инстанс обрабатывает только какого-то одного своего клиента, закинутого на него балансировщиком.
Как по мне приведенный пример это как раз и есть про "несколько инстансов". В общем, случаи если у вас есть один сервис который дает 100 RPS, и 4 последовательных сервиса дающих 100 RPS, то на то и выйдет за минусом сетевого оверхеда. Вопрос лишь в том, что обычно микросервисы выполняют меньше работы и более специализированы, и могут быть проще оптимизированы.
Второй вопрос, это деплой монолита, если микросервис может быть обновлен, при условии сохранения обратной совместимости, усилиями одной команды, то с монолитом на тысячу инстансов это уже проблема. Да и предсказуемость лучше, когда старые сервисы постепенно выводятся и заменяются на новые.
Любой сервис на тысячу инстансов это сложно. И не важно как вы его сделали.
У микросервисов на самом деле есть проблема умножения РПС. Наиболее микросервисные штуки умудряются довести коэффициент РПС до 50. Может бывает и больше, но я только 50 видел.
И потом получаем мужественную борьбу с десятком тысяч РПС. А откуда он взялся вообще непонятно никому. На балансерах в которые идут пользователи видны нормальные сотни РПС.
До микросервисов надой пройти путь, а вернее дорасти. Большие проекты не просто так пришли к этой концепции, потому что кому-то захотелось поиграть в абстракции и поупражняться в архитектуре. А то что, это превратилось в карго культ, и любое Рога&Копыта - хочет так же, хотя им это и не нужно. Да это объективный факт, с этим трудно спорить.
Зато в резюме смотрится внушительно "сервис с нагрузкой 100500RPS", правда на самом деле это оказывается 100RPS в базарный день от клиентов, но у нас же 50 микросервисов обменивающихся информацией и производящих синхронизацию данных.
Видел решение когда на каждое изменение в микросервисе юзеров всем остальным рассылался апдейт данных на случай если они у себя что-то меняют. Было около 20 подписчиков каждый из которых был запущен в нескольких экземплярах для надежности.
Во-первых, для поддержания оной модульности в монолите нужна очень сильная рука, ибо без нее у разных команд периодически будет стремление сделать как проще, особенно когда сроки горят. Во-вторых, все монолиты, с казалось-бы красивой модульностью что я видел, в них модули в итоге все работали с одной базой данных. Да, есть слой бизнес-логики, разбитый на отдельные модули, есть слой работы с базой данных, разбитый на модули, но база данных одна. А приводит это к тому, что разные модули работают с одними и теми-же таблицами. Есть всякие красивые запросы на много таблиц, ну а что, клево-же, очень быстро, достаем все данные. И как итог, все равно высокая связанность. Надо добавить поле в базу данных - в любом случае весь монолит надо прогонять всеми-всеми тестами, ибо может вылезти боком в неожиданном месте.
Микросервисы же изначально делают так, чтоб каждый сервис работал со своей базой данных и никого туда напрямую не пускал. Как итог, все эти обновления когда надо что-то поменять в структуре данных, проходят гораздо быстрее и легче. Ну если не пилить на совсем уже микро-микро сервисы, тогда появляются отельные головные боли с распределенными транзакциями. Вообще, на мой взгляд, микросервисы должны быть не слишком мелкими, довольно крупными.
Теперь дальше проблемы монолитов с модулями: одной команде надо переехать на новый фреймворк. А остальным не надо. Начинается бодание. Потом головная боль, когда все переезжают к определенному сроку. Одной команде надо обновить СУБД. А какой-то другой команде очень надо оставаться на старой. Опять головная боль.
Не знаю как там в большом программировании, а в 1С чем дальше тем больше бьют по рукам пытающихся работать с объектной моделью. И всех загоняют в табличную. Где да, "всякие красивые запросы на много таблиц" которые отдаются в нормальную СУБД, которая на фильтрах, соединениях и выборках собаку съела и быстро отдает результат.
А идеи "а давайте выдернем табличку с фильтром, потом результат отдадим как фильтр в выборку из другой таблички, потом соединим на клиенте с выборкой из третьей" остались в конце девяностых или даже раньше. Не надо оборачивать каждую таблицу в сервис и делать по сети десяток запросов эмулируя работу планировщика запроса СУБД. У вас это получится хуже, чем у профессионалов.
Я и не говорил, что надо на каждую табличку свой сервис делать.
А так, в 1с еще с 90х был язык запросов, позволяющий работать с объектами. В 7.7 был, наверняка и в 7.5 был, но уже точно не помню. Если до сих пор он все данные тащит на клиента и там работает с ними, вынуждая вас работать с таблицами на прямую, когда нужна производительность то это очень печально. Для вас, как разработчиков. В мире не-1с обычно есть слой ORM, который преобразует запросы к объектным моделям в нормальный sql запрос который и выполняется в базе. Я очень люблю дотнетовский linq - язык работы с коллекциями объектов, вот он нормально ложится на sql, и даже если, для какого-то хитрого запроса orm не справляется - его можно расширить самому.
Нет, я не об этом. Я про то, что если у вас в каждом сервисе своя БД, то вы не можете построить эффективный запрос использующий данные из всех этих БД и будете изобретать свой планировщик запросов поверх микросервисов.
Ну то есть грубо говоря, сначала выберете все заказы на сегодня в одном микросервисе, потом схлопните этот список заказов до списка уникальных контрагентов, потом в другом микросервисе будет выяснять телефоны и контактых лиц контрагентов чтобы вывести менеджеру табличку, кому он должен сегодня звонить.
Вместо того, чтобы сджойнить таблицу заказов с таблицей контактной информации по контрагенту и уложить это в одно сетевое обращение к одной БД.
Далеко не всегда необходимы данные из нескольких сервисов одновременно, хотя конечно бывает и так. Обычно все начинается с монолита, а когда он становится настолько большим, что уже мешает работе, что на задачи на которые раньше уходили часы теперь тратятся дни, если не недели, приходят к пониманию, что уж слишком большой и надо как-то его начать пилить и отпиливают в первую очередь куски, которые слабо пересекаются с остальными частями. Там где сильная связанность и никак не распутать, могут вообще оставить одним куском. Хотя чаще объявляют друмучим легаси и переписывают с нуля. В общем, все равно пересечений не избежать, но стараются, чтоб их было как можно меньше.
Далее, ваш случай, допустим так и есть, где-то нарезали так, что есть отдельный сервис контрагентов и отдельный сервис с заказами. UI обычно не работает напрямую с микросервисами, чаще всего работает с API слоем, который уже транслирует запросы к нужным сервисам. В вашем случае у сервиса заказов будет отдельный метод, типа "айди уникальных заказчиков за период", а у сервиса контрагентов будет метод "получить список контактных лиц контрагентов по идентификаторам контрагентов", так что слой АПИ сначала сделает вызов к первому методу, потом полученные от него айдишники пошлет во второй метод и получит нужный результат. Конечно вызов двух сервисов будет в итоге медленнее, чем один запрос в базе, ну так идеальной архитектуры не бывает, везде есть свои плюсы и минусы.
Угу, а еще студента-программиста принято бить канделябром, если база данных не нормализованна, и это правильно. Однако есть некоторые сценарии, где денормализация таблиц оправданна и вполне себе применяется, и даже те-же самые 20-30 лет назад применялась.
Типичная где? За 25 лет работы с базами данных я повидал всякие, как правило, если рабочая база под сотню таблиц и выше, там можно будет найти денормализацию, специально туда привнесенную.
Только вот типичная коммерческая разработка даже близко к этому сценарию не приближается.
В типичной коммерческой разработке денормализация данных встречается сплошь и рядом. Как минимум, в любой компании, где есть не только транзакционная база, но и аналитика. В принципе, у денормализации как инструмента основное применение, это увеличение производительности выборок за счёт увеличения требований к дисковому пространству и увеличения времени вставки. И денормализация в базах, где присутствуют тяжёлые выборки, привычное явление.
Микросервисы же изначально делают так, чтоб каждый сервис работал со своей базой данных и никого туда напрямую не пускал.
Я не могу сказать, что это какое-то достоинство или недостаток, это просто особенность реализации, которая иногда может быть уместна, иногда нет. Хорошо, если микросервисы настолько модульные, что могут себе позвоить иметь разные базы данных. А если данные между собой имеют логическую связность? Ну, например, вот у нас есть микросервис филиалов, вот у нас есть микросервис заказов, микросервис клиентов. Заказы связаны с филиалами и клиентами, клиенты - с филиалами. Работая в одной базе, вы можете обеспечить целостность данных на уровне базы данных. Например, банально не дать удалить клиента, у которого есть заказы. Раскидав это по разным базам, ключей у вас больше не будет, контроль целостности данных вы будете обеспечивать самописными и весьма нетороплиывыми костылями, микросервис клиента будет дёргать микросервис заказов, проверяя, есть ли там заказы по текущему клиенту, чтобы разрешать или запрещать удаление, и т.д.
Ну я сразу и написал, что люблю сервисы по крупнее, по мне так если пара команд работает над одним сервисом, то это еще нормально. Хотя в любом случае, когда начинаешь нарезать на сервисы, без межсервисного взаимодействия не обойтись, но можно постараться нарезать так, чтоб такого взаимодействия было как можно меньше.
В целом же, серебряной пули нет, везде есть свои достоинства и свои недостатки, надо четко понимать, что делаешь и зачем именно, а не гоняться за хайпом.
Вот и представьте, что у вас есть таблица клиентов, таблица заявок и таблица заказов и все микросервисы вашего приложения их используют - правильно я понимаю, что все эти три неслабых таблицы вы будете реплицировать между всеми микросервисами?
Чтобы time-to-market был минимальным, нужно параллелизовывать работы как можно круче. Чтобы программистов привлекали к проработке задачи как можно раньше, чтобы программисты всех частей (бэк, фронты, хер знает кто еще) в первую очередь согласовывали между собой контракт, а потом уже начинали что-то делать, естественно параллельно, чтобы опсы заранее знали о крупных фичах и планировали инфраструктурные апгрейды под релизы как можно раньше, чтобы тестировщики начинали накидывать тест-кейсы когда задача спроектирована, а не когда разработка закончила, чтобы техподдержка так же была в курсе того, что ее вскоре ожидает, могла как-то к этому подготовиться, например внести какие-нибудь предложения по разработке дополнительного тулинга для них.
А микросервисы к time-to-market докидывают не так уж много, по сравнению с монолитом: простые миграции хранилищ, да возможность без лишних согласований завезти нужные версии инструментов и библиотек, это важно, но с этим сталкиваешься далеко не на каждой фиче. Возможность говнокодить в микросервисе и вовсе может сыграть злую шутку при его разрастании. MSA -- это не про размеры сервисов, это про микроинтерфейсы к сущностям и необходимый минимум ручек для каждой из них. Их может быть три-пять, но с таким адом внутри, что лучше было не говнокодить с самого начала.
Вечный холивар) плодородная почва!
В правильной организации разработчики делятся на core platform и functional modules.
И весь этот горький катаклизм... микрокомпонентный хайп уже был минимум дважды. И дважды обходился дорого.
Пора уже операционные системы затачивать под микросервисы.
Кажется, автор никогда не работал над монолитами, но яростно их осуждает используя чужое мнение.
кажется, лучше писать конкретные аргументы, чем делать странные предположения
Справедливо. Единственный пример и аргумент автора в статье против монолита - "Я честно не понимаю". Так надо задавать вопросы, а не фантазировать как "десятки ДБа чахнут над перегруженными базами".
Монолиты в своей среде - весьма структурированы и разделяемы на модули (иначе бы просто не выжили). У каждого разработчика есть возможность заглянуть (в один клик) в код соседей и улучшить его и научиться новому (соблюдая кодекс чести). Каждый разработчик может всё и можно исправить за один чих кучу компонентов. И задеплоить их одновременно, а не синхронизировать работы в куче команд.
Касательно десятков ДБА, так в микросервисной среде их будет не меньше. Базы есть, присматривать за ними надо. А вопросы перегруженных БД - так это вопросы архитектуры проекта и модулей. В микросервисном подходе получить перегруженную БД ничуть не сложнее.
изменить код соседей да, легко, а вот быстро сбилдить, прогнать тесты и выкатить - не получится, плюс потребует синхронизации с другими командами
Утрированный пример: если есть отдельный микросервис, с помощью которого можно поменять цвет кнопки, или там, комиссию чего-нибудь, то от идеи "поменяй на красный" до продакшена пройдет 10 минут. В случае монолита может быть что угодно: от просто долгого билда, до фриза всех фич пока "идет рефакторинг чего-то там" или работы с бд. Суть в том, что в монолите зачастую ты не можешь просто и быстро выкатить. С точки зрения доступности кода - да, монолит лучше
я имею в виду монолит большого размера, где 5-10 или даже 50 команд над ним работают
В вашем утрированном примере подготовлена база, что цевет кнопки "зашит" в одном микро-сервисе. Попробую подыграть вам в вашем утрированном примере. А что если для изменения цвета кнопки надо знать платная ли у пользователя подписка, а информации о профиле в этом месте нет? То есть надо не константу поменять, а условие хождения к соседнему микросервису добавить, а в запросе про цвет кнопки даже user-id отсутствует...
PS не все языки программирования требуют компиляции. А тесты монолита делятся на модули в соответствии с делением кода.
условие хождения к соседнему микросервису добавить,
зависимости бывают, конечно, бывают и на другие команды. Но очень часто бывает и без зависимостей: данные собирать из существующих топиков кафки, эндпоинтов и т.д. Очень важно тут разделение на доменные области, чтобы команда "владела" необходимыми микросервисами.
А в монолите по определению всё зависит от всего.
PS не все языки программирования требуют компиляции. А тесты монолита делятся на модули в соответствии с делением кода.
если монолит такой, что можно быстро внести изменения в какую-то часть и выкатить за 10 минут, ни с кем вообще не согласовывая, то это ОК, микросервисы не нужны.
На практике же пока что не видел такого.
Представьте себе, что для изменения в таком монолите, например, достаточно перепрописать одну хранимую процедуру в общей базе данных (при условии, что её интерфейс не изменился) и всё встанет на своё место. Я пилит монолит в масштабпх банка (АБС) порядка 10 лет и каждую неделю выпускали по версии, при необходимости могли делать изменения ежедневно.
Знакомый, который уже почти 20 лет поддерживает приложение на FoxPro, тоже удивляется, всем этим глупым микросервисам, а ещё удивляется, откуда появляются и зачем нужны кучи языков, это всё глупая трата денег и времени. При чём искренне так. А ведь его детище 20 лет живёт и даже вполне работает :)
Речь не про "можно" или "нельзя", а про скорость и качество. Нельзя в монолите пропатчить какую-то там хранимку, не протестировав весь функционал полностью, так как в монолите любое изменение -- это влияние на весь проект.
Разве пакаджи в яве не для того придуманы, чтобы разделять логику (в том числе монолитного) проекта на множества, пересекающиеся только публичными интерфейсами?
(в других языках тоже вполне себе есть понятия для выделения изолированного модуля)
Нельзя обновить пакет в работающем приложении, при малейшем изменении в любом пакете, требуется пересобирать и редеплоить всё приложение.
Любой модуль приложение в состоянии положить всё приложение целиком.
Любая зависимость любого модуля становится зависимостью всего проекта в целом. Обновление зависимости, способно поломать работу других модулей, или скрытно изменить их логику.
Никто не отменяет модульный подход при разработке микро-сервисов. Микро-сервис от монолита отличается только тем, что он реализует один ограниченный контекст, в то время, как монолит реализует неограниченное количество ограниченных контекстов.
Допустим, возникла потребность закупить библиотеку, решающую какую-то алгоритмическую задачу. Но из-за монолита компания ограничена только в выборе решений в рамках своего технологического стека, или хотя бы совместимым с ним. С микросервисами такой проблемы не стоит в принципе. Проект может быть написан с использованием Java, PHP, Node.js, Go -- никаких ограничений.
Любой модуль приложение в состоянии положить всё приложение целиком.
Как, если он общается только через интерфейсы. В таком случае и любой микросервис способен сделать то же самое.
Допустим, возникла потребность закупить библиотеку, решающую какую-то алгоритмическую задачу. Но из-за монолита компания ограничена только в выборе решений в рамках своего технологического стека, или хотя бы совместимым с ним.
Моя 1С уже стала микросервисной от того что дергает то COM, то куски написанные на питоне?
Как, если он общается только через интерфейсы. В таком случае и любой микросервис способен сделать то же самое.
Какая разница как там модули друг с другом общаются, если они работают в едином процессе, в одном пространстве?
Если зависнет микросервис, то просто перестанет работать функция, которую он реализует, но не всё приложение целиком. Более того, окрестратор будет пытаться автоматически восстановить работу сервиса. При повышении нагрузки именно на конкретный микросервис, может быть выполнен скейлинг.
Моя 1С уже стала микросервисной от того что дергает то COM, то куски написанные на питоне?
Нет конечно, так как COM-сервер выполняется на той же машине, на тех же ресурсах без какой-либо возможности управлять квотами на ресурсы. И COM-сервер легко может положить на лопатки всю 1С, выжрав всю память или CPU, да и диск может просто тупо забить под ноль.
Опять же. 1С+COM это винда, не всё можно запускать под виндой.
Вы это серьёзно про обязательное перетестирование всего монолита из-за изменения произвольной (но известной) хранимки?
Про трассировку требований, кода ничего не слышали?
Если бы так было, то монолиты не смогли бы развиваться. А так, известные мне монолиты, которые мы эксплуатируем, например, выпускают релизы раз в две недели и неплохо себя чувствуют.
Давайте разберём по тезисам:
Как должно быть и как в реальности -- чаще всего отличается
Трассировка требований -- это трудозатраты, и не панацея (люди ошибаются, внимательность не 100%)
Хранимки вообще плохо уживаются с CI/CD и полной автоматизации непрерывного цикла разработки/тестирования
Изменение хранимок это манки-патчинг, крайне сложно (до невозможного) обеспечить blue/green, canary releases на хранимках.
ИМХО, можете минусовать, кидать в карму, но логика в хранимках -- абсолютное зло, и это один из худших поворотов в истории разработки ПО, которое сделало человечество
Все монолиты неплохо себя чувствуют. В моей организации есть огромные монолиты, которые живут от 2005 года, они работают, в них есть хранимки, они работают и развиваются.
Поэтому я не утверждаю ни в коем случае, что монолиты это плохо, или там жизни нет. Но опыт разработки показывает, когда мы из монолита выкорчёвываем какой-то функционал и отселяем в отдельный сервис, становится лучше по всем фронтам, time 2 market подскакивает, разработка и выпуск релизов становится проще, быстрее, деплой чистый и открывает кучу возможностей.
И ещё есть очень важный элемент. Извлечённый функционал из монолита иногда становится функцией, которую могут переиспользовать другие продукты, совершенно независимо от развития проекта, откуда функция отпочковалась. Другими словами микросервисы -- это ещё про коммунализацию функций.
А об этом что-то совсем не говорят ни в каких статьях
Утрированный пример: если есть отдельный микросервис, с помощью которого можно поменять цвет кнопки, или там, комиссию чего-нибудь, то от идеи "поменяй на красный" до продакшена пройдет 10 минут
В общем случае внести простое изменение в монолит по трудоёмкости занимает ровно столько, сколько и в микросервис. Ну потому что ответственная за модуль команда берёт и вносит это изменение, а потом просто собирают всё вместе и публикуют. Да, есть какой-то выигрыш собственно по времени публикации, но это делает бездушный робот, и в общем-то пофигу, десять там минут оно занимает или сорок. Фризить все фичи - ну как бы такой необходимости на современных системах контроля версий уже нет. Есть какая-то опубликованная текущая версия, в её ветку вносятся только протестированные и согласованные изменения. Т.е. мейнтейнеры сделали у себя, потом смерджились с идущей на публикацию веткой, ну и оно там пошло в прод.
А что если надо откатить баг, а за это время 100 человек уже написали овердофига нового кода?
Так же как и на микросервисах: оставляете несколько версий фичи и держите их несколько релизов. А при необходимости переставляете флаг обратно и возвращаетесь на прошлую версию
Монолит или микросервисы — это не вопрос технологических предпочтений, это про time-to-market