Комментарии 36
Эта песня хороша, начинай сначала!
А можно конкретные примеры сравнения примерно одинаковых продуктов по монолиту и микросервисам? Я на Хабре видел только один пример и он совсем не в пользу микросервисов.
https://azhidkov.pro/posts/23/07/project-e-results/
Переход с микросервисов на монолит
На мой взгляд, наибольший вклад в увеличение скорости разработки внёс переход на монолит. Пусть он будет ответственен за 32% улучшения. Из цифр видно, что версию на монолите сделали на 20-30 процентов быстрее (смотря что на что делить). И я думаю, что это консервативная оценка - если бы kotlin-версию делал также один мидл, то он сделал бы в два раза/на 50% быстрее. По крайней мере, для себя я сделал вывод, что делать проекты до человеко/года на микросервисах как минимум в два раза дороже, чем на монолите.
Спасибо за ссылку, вывод автора о том, что "делать проекты до человеко/года на микросервисах как минимум в два раза дороже, чем на монолите" в целом соотносится с нашей практикой. Не уверен, что в 2 раза, но точно дороже. У нас не было опыта разработки 2-х в целом одинаковых приложений в разных архитектурных подходах: каждое приложение имеет ряд особенностей, поэтому сравнивать монолит и микросервисы "при прочих равных условиях" не представляется возможным. Хочу отметить, что и у монолита, и у микросервисов есть свои плюсы и минусы. Статья нацелена на то, чтобы подсветить их и чтобы выбор того или иного подхода был осознанным
продублирую свое мнение про обоснованность микросервисов в разного типа и масштабах проектов - давайте сравним
Какие бывают доводы:
Требования к безопасности. Например, платежи почти всегда это отдельный модуль.
Уже есть несколько модулей, унаследованных или закупленных
Много команд разработки, сложности в их координации. Обычно, это играет роль при масштабе от 10 команд от 10 человек каждая. И только при условии что предметная область хорошо известна, не меняется. Иначе, изменение границ домена ведёт к большой переделке. Monolith first это не просто так придумали.
Чертов легаси, который надо сопровождать, но его никто не понимает. Легаси плавно начинается с ухода разработчика этой части кода и с ухода архитектора.
Мультитехнологические команды
Высокие требования к масштабированию (ага, не тянет на 100 ядерном сервере) или требования к географической распределенности
Ещё CI/ CD когда один из модулей меняется несколько раз в день. Но это решаемо и дешевле. Разве что если бизнес создаёт огромный поток ad-hoc нешаблонных задач, которые не будут развиваться, а команды перекинут через пару месяцев на другие галеры. Такой мусор, действительно, стоит изолировать в виде отдельного сервиса, чтобы стоял и не мешал никому.
Желание команды потренироваться это плохой довод.
Есть идиотская ложная дихотомия «монолит или микросервисы», которая придумана инфоцыганами и тиражируется всеми, кому не лень.
На самом деле, есть прекрасная архитектура «монолит и микросервисы» (и лямбды еще иногда) — которая лишена всех недостатков и наделена всеми достоинствами апологетов любого решения из предыдущего пункта.
Там, где удобнее и лучше монолит — используем монолит (на каком-нибудь ООП-языке, причем, хоть джава, хоть руби). Сервисные части — отчуждаем в сервисы (обычно на чем-нибудь высоконкурентном и простом, типа эликсира или даже го, при всем моем к нему отвращении). В лямбды пихаем всю одноразовую некондицию (вот для этого есть хорошая библиотека на питоне — значит, питон, вот это чистая функциональщина — хаскель, или фшарп, и так далее).
И всё. Нет дилеммы — нет проблемы, как говаривал Иосиф Виссарионович.
Не понимаю что именно вы имеете в виду, я просто принимаю решение об изоляции вот этого конкретного куска одним из вариантов изоляции
MSA (вместе с БД), EDA (можно и на одной БД, зависимости по данным не будет, так как события дают слабую связность),
SOA (без разделения БД, общение XML а если много сервисов то ESB прикрутить),
SBA (код разделяем , а БД нет, много сервисов нельзя, будет много связей)
изолировать CQRS части, отделить requests от commands (один апп и база для commands, второй апп и база агрегированных данных для аналитических requests).
Я не знаю, что такое MSA, EDA, SOA, SBA, CQRS, поэтому внятно ответить не смогу.
Я имел в виду всего лишь, что не существует дихотомии «Микросервисы vs Монолит» из заглавия текста выше.
Я не знаю, что такое MSA, EDA, SOA, SBA, CQRS
Я же расписал всё: паттерны отдельно или вместе деплоить код, данные, формат связей и преобразование данных в случае CQRS. Для каждой части приложение свое решение. И по умолчанию монолит)
что не существует дихотомии «Микросервисы vs Монолит» из заглавия текста выше
В такой формулировке не существует.
Согласен, мы также пришли к выводу, что у обеих архитектур есть свои сильные стороны, поэтому применяем обе архитектуры в своей работе
на практике возьмём крупную компанию. Что в ней?
каждый микросервис буквально фашистскими мерами загнан в единые рамки:
вот этот язык (и нужно очень сильное обоснование для построения сервиса на другом языке)
вот этот набор библиотек для логгирования/метрик и так далее
вот этот кодогенератор из описания протокола в код сервера
вот этот кодогенератор клиентов
вот этот способ деплоя
Если вести речь о масштабировании, то тут глобально всего одно узкое место масштабирования - выбранная БД (или выбранные БД), доступные методы масштабирования не зависят от микросервисности:
очереди
распределённые БД
Команда, понимающая "систему в целом" требуется всё равно (и в микросервисной архитектуре требования к её экспертизе выше)
Итого, средний микросервисный стек - это тот же монолит, вид сбоку, у которого из преимуществ разве что возможность деплоя его по частям. Впрочем, большие монолиты тоже, как правило, деплоятся по частям.
Согласен.
Введут микросервисы по предлогом свободы. А потом захочешь на rust вместо go, а девопсы и говорят: а мы не умеем.
Что касается рамок микросервисов, в целом согласен - с точки зрения компании унификация стека является большим преимуществом: компания накапливает опыт работы с конкретными технологиями, быстрее решает инциденты и реализует фичи. Однако в нашей практике есть проссплатформенные приложения (часть модулей написана на C#, часть - на Java). Также в нашей практике есть опыт миграции части монолита на новые технологии: миграция всего монолита была слишком дорогой, но небольшой кусок функционала был переведен на новые технологии. Еще отмечу, что мигрировать на новые технологии микросервисы проще: можно начать миграцию с наиболее простых микросервисов, постепенно переходя к более сложным модулям. При внедрении новой технологии надо учитывать много разных факторов, один из них - техническая возможность дешевой встройки новой технологии. Микросервсисы дают такую техническую возможность, но, конечно, не закрывают организационные и другие вопросы.
Что касается масштабирования, то оно не всегда упирается в БД. Есть куски приложения, которые сильно нагружены по CPU. Такие куски масштабируются не за счет БД, а за счет распараллеливания вычислений.
Что касается пункта про команду - согласен, требуется понимание целиком, как устроен продукт, однако это понимание не обязательно должно быть у всех членов команды
Что касается масштабирования, то оно не всегда упирается в БД. Есть куски приложения, которые сильно нагружены по CPU. Такие куски масштабируются не за счет БД, а за счет распараллеливания вычислений.
Погодите. Те вещи, которые решаются простым добавлением узлов называются масштабируемыми. Если что-то параллелится - оно масштабируемо.
Я говорил о том, что проблемы масштабируемости наиболее частотны около БД. А всё остальное обычно масштабируемо итак: упёрся в CPU? Добавил инстансов (CPU). Упёрся в сеть? Добавил инстансов в другом сегменте сети.
А упёрся в память - это пробема уровня in-memory БД. Здесь вопрос как поделить на два шарда - вопрос уровня БД.
Если правильно понял, то Вы имеете ввиду, что есть вещи, которые легко масштабировать (например, вычисления легко масштабируются путем добавления CPU), а есть те, которые сложно масштабировать (если мы уперлись по производительности в БД, то реинжениринг базы это, действительно, дорогая задача). Хочу отметить, что монолит сложнее масштабировать за счет добавления ресурсов: мы не может дать CPU только высоконагруженной части приложения, а микросервисы позволяют масштабировать только те куски приложения, которые действительно в этом нуждаются
Так а чем монолит в этому случае поможет? В микросервисах хоть потенциально такая возможность имеется. Где-то при необходимости можно и раст использовать вместо go, если на то есть реальные причины, а не потому что захотелось
Микросервисы
Необходима чёткая декомпозиция системы на модули с отдельными бизнес-областями.
Простите, очевидно, подразумевается, что в "монолите" это не нужно? Я бы поспорил. А как только мы грамотно поделили "монолит" (кавычки не случайны) на бизнес-сущности, взаимодействующие через стандартизованные интерфейсы – сразу появляются и возможности независимой разработки, изолированного внесения изменений, бесшовного (за счёт изменения конфигов) подключения специфичных для конкретного заказчика модулей и вообще буквально все те плюшки, которыми так гордятся МС. При отсутствии необходимости городить сложную инфраструктуру оркестрации внутрисистемного взаимодействия.
Не нужно сравнивать МС с плохо спроектированными "монолитами" – сравнивайте с хорошими. И может быть, тогда всё будет выглядеть менее благостно.
Есть момент: изоляция микросервиса происходит ещё при живом архитекторе и разработчике, а потом сервис может долго существовать в виде гниющего трупа когда все уже ушли и никто ничего не понимает. Но довод звучит так себе, верно?
Конечно, декомпозиция нужна и в монолите, однако в монолите проще забыть про декомпозицию и сложнее поддерживать четкие границы по сравнению с микросервисами
в монолите проще забыть про декомпозицию
Тут согласен. Но тогда и статья должна быть совсем о другом: Микросервисы как лекарство от склероза и разгильдяйства. Дарю название. Однако:
Как только команда, разрабатывающая "монолит", начинает придерживаться принципов хорошего проектирования, она получает все описанные в статье преимущества МС без необходимости усложнения инфраструктуры;
Если трансформировать пропагандируемый свидетелями МС подход "один микросервис – одна команда" в "один бизнес-модуль – одна команда", то неожиданно получится ровно тот же уровень декомпозиции: каждая команда пишет своё, руководствуясь только спецификацией и не оглядываясь на других. Правда, так очень редко делают – просто в силу нерациональности. Гораздо эффективнее иметь некое общее ядро, а не заставлять каждую команду реализовывать одно и то же по-своему.
Ахахх) "Микросервисы как лекарство от склероза и разгильдяйства" отличное название) подумаю о выпуске цикла статей о разных лекарствах, которые должны быть в арсенале любого уважающего себя разработчика)
Насчет работы нескольких команд над монолитом - да, такая практика возможна. Но надо понимать, что и там могут быть минусы, например, частые конфликты при одновременных изменениях в ядре. Я не утверждаю, что монолит - это плохо, но у каждого подхода есть свои плюсы и минусы
технически не сложнее
а вот без тех людей, которые все спроектировали и написали - сложнее " поддерживать четкие границы" и монолит с бОльшей вероятностью превращается в сильно помойку сильно зависимых компонент
:-) Вопросы по эксплуатации у клиента ПО (связанные с ее стоимостью) видимо сознательно упущены? :-)
Что имеете ввиду? Что микросервисы дороже в эксплуатации?
Автор, у вас ошибка. Взаимодействие между микросервисами происходит не через апи а через брокер, подобно тому, как в ООП объекты взаимодействуют через сообщения. И нужно это для того, чтобы убрать неравномерность нагрузки.
Где распределенные транзакции, которые являются неотъемлемой частью мса?
Как обычно, происходит путаница мса с распределенным монолитом.о С таким же успехом можно и субд назвать микросервисом.
Взаимодействие между микросервисами происходит не через апи а через брокер […]
Это вообще не обязательное условие. Хоть почту шлите, а там принимайте. Или положите файл в S3 — и забирайте его оттуда.
Где распределенные транзакции, которые являются неотъемлемой частью мса?
С каких пирогов они — неотъемлемая часть? RPC в RabbitMQ появились уже после термина «микросервис». Сага — вообще мертворожденное поделие. А еще, распределенная транзакция — синхронна для вызывающего процесса, что полностью противоречит концепции «как в ООП объекты взаимодействуют через сообщения», потому что сообщения синхронными не могут быть по определению. Любая синхронизация — всего лишь синтаксический сахар поверх асинхронных сообщений.
Под брокером сообщений я понимаю в целом, асинхронное взаимодействие с микросервисами, когда результат работы микросервиса являет отложенным. В этом суть проблемы и именно этот навык интересует у разрабов, которые будут микросервисы проектировать, а не просто развернуть какую то приложуху и дернуть её через рест грпц апи.
результат работы микросервиса являет отложенным
Отложенным — в смысле асинхронным? Или не мгновенным?
Вы вон сами распределенные транзакции упомянули, а они синхронны (хоть ответ и отложен). В общем, «развернуть и дернуть через rpc» — иногда тоже прекрасно работает, и микросервисом быть не перестаёт, особенно, если оно стейтфул.
Не соглашусь: микросервисная архитектура не говорит о том, что сервисы обязаны общаться друг с другом только через брокер. Есть множество способов общения между сервисами. В нашей практике мы, как правило, используем очередь сообщений и web-api.
Что касается распределенных транзакций, то, на мой взгляд, это антипаттерн: трудозатраты, связанные с отладкой и расследованием проблем таких транзакций, крайне велики. В микросервисной архитектуре есть другие способы поддержания целостности данных (например, паттерн Outbox и Saga, о которых буду рассказывать в следующей статье из цикла).
СУБД не является микросервисом, поскольку микросервисы должны строиться вокруг бизнес-потребностей (а не технических компонент).
Микросервисы vs Монолит: плюсы и минусы