Pull to refresh

Comments 180

Микросервисы — это естественная реакция разработчиков «средних» компаний на изменившиеся условия. Писать всё своё с нуля могут только крупнейшие игроки (Apple/Google/Microsoft), но и там это считается антипаттерном NIH. А все остальные вынуждены юзать тонны чужого кода от разных вендоров.
С другой стороны, появление этих ваших гитхабов и гибких методологий привело к rolling release-ам, точнее к отсутствию релизов как таковых. Есть поток отладочных версий библиотек с кучей багов, которые никто не собирается фиксить, а вместо этого просто выкатывают новую, несовместимую со старой версию со своими свежими багами.
Вы начинаете более-менее крупный проект, берёте свежайшие либы и, пока дойдёте до версии 1.0, выясняете, что ваши либы устарели уже на пару мажорных номеров. С монолитом просто так взять и обновиться нельзя, нужно переписывать кучу кода и заново его тестировать.
Микросервисы решают этот вопрос тем, что позволяют себя переписать на новой либе или вообще новом языке за те пару месяцев, пока версии ключевых либ считаются «свежими».
Плата за это — да, налог на девопсов, а также сложноуловимые баги «между» микросервисами, когда непонятно, кому вообще заниматься отладкой.
> С монолитом просто так взять и обновиться нельзя, нужно переписывать кучу кода и заново его тестировать.

С микросервисами тоже просто так обновится нельзя, переписали сервиси — надо так же все тестировать, где гарантия что сервис переписан коректно.

> Микросервисы решают этот вопрос тем, что позволяют себя переписать на новой либе или вообще новом языке за те пару месяцев, пока версии ключевых либ считаются «свежими».

Пока переписываем микросервис — либы опять устаревают? тут наверное нужно гнаться не за либами — а найти компромисс между «старыми» либами и работающим функционалом.

UFO just landed and posted this here
Надо будет прогонять бизнес тестирование что для монолита, что для маленького сервиса — по трудозатратам выходит одинаково. А функционально проверить изменения и в монолите можно если это не спагетти код.

Плюс спорный вопрос, что тестить проще. Если монолит целиком переписать и потом его тестировать — то ну его нафиг, так вообще не полетит. А если сделать roadmap для переезда на новую платформу(ради чего мы переписываем), то изменения можно будет да же под бизнесовыми задачам провести и протестировать.
Боюсь, без измерений все заявления, что «будет быстрее» или «будет затрачиваться столько же времени» — беспочвенны, пока мы не проведём конкретный эмпирический тест, чистота которого, так или иначе, будет весьма сомнительна.

Однако, в целом, вы пишите фактически только про изолированность, документированность и чистоту кода.
Однако, микросервисы — это уход, в первую очередь, от инфраструктурных проблем.
Потому что монолит — требует, чтобы одна единственная машина могла предоставить все необходимые пакеты(модули) и все необходимые ресурсы требуемые для решения задачи одновременно.
Когда речь идёт о каком-нибудь многоуровневом стэке технологий(когда одни библиотеки опираются на кодовую базу других) — все хорошо.
А вот как только вы используете разноплановые библиотеки из разных технологических стеков — запуск и развертывание монолитного решения становится задачей почти фантастической, т.к. постоянно вылезают противоречивые требования или прямые несовместимости библиотек.
А вот когда дело доходит до обработки больших данных… ух. Тут микросервисы, каждый из которых должен анализировать свой кусок данных на недорогих инстансах 4+4(4 vCPU+4GB RAM), или давать быстрый ответ для пользователей в своей географической зоне — незаменимы.
К тому же, в тех же направлениях распределенных вычислений фрагментация пакетов-модулей — гораздо выше, чем в «традиционных» областях, что создаст огромное количество проблем при попытке обновления каких-то библиотек в монолите.

Так что — все зависит от поставленной задачи, которая диктует выбор технологического стэка(или россыпи).
Если ваша задача решается стэндалон, или единичным сервером на «стратифицированном» технологическом стэке — вполне вероятно, что монолит — будет хорошим решением.
Если же нужна распределенная система, или большое количество несвязных модулей/библиотек — добро пожаловать в микросервисную архитектуру.
Ну и CI/CD, как правило, все-таки гораздо легче, как минимум по машинным ресурсам — решается на микросервисах.
UFO just landed and posted this here
Инфраструктура инфраструктуре рознь. С микросервисами растёт сложность инфраструктуры оркестрации, диспетчерезации и т. п., но падает сложность инфраструктуры локальной среды исполнения. Например, в микросервисах нет необходимости синхронизировать версии одной библиотеки, используемых в разных модулях, а в монолите может оказаться не обойтись без переписывания кода.
Инфраструктура для набора микросервисов, решающих те же задачи, что и монолит — сложнее по построению.
Переход на микросервисы сам по себе ничего не упрощает, но превращает часть внутрипроцессных вызовов в медленные, ненадежные, плохо контролируемые на соответствие соглашениям сетевые.
И все это ради единственного преимущества: селективного горизонтального масштабирования.
Навскидку ещё два: селективный деплой и (в теории) возможность работы в режиме частичного отказа.
В частичный отказ монолит «умеет» и самостоятельно.
Селективный деплой для монолита сложнее, но также возможен при аналогичном подходе к проблемам совместимости.

Я всегда думал, что "частичный отказ" подразумевает поломку сервиса, сопровождающейся простоем.
Если сервис "один из..", в микросервисной архитектуре — получаем как раз "частичный отказ". Если сервис "всего один", как монолит — то либо работает либо нет. Как может "частично" работать (а вернее "частично не работать") монолит в данном контексте — не понятно.

как монолит — то либо работает либо нет.

может же быть несколько экземпляров.

Как может «частично» работать (а вернее «частично не работать») монолит в данном контексте — не понятно.

ну например, повреждена БД.
операции с ней невозможны.

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


С этим не все так просто.

Возьмем конкретный ясный всем пример — интернет-магазин.

Не работает хоть что-то из этого: корзина, каталог товаров, оформление товаров, прием оплаты-онлайн. У вас нет интернет магазина.

То, что работает при этом уведомление пользователей по СМС, уведомление пользователей по e-mail, полнотекстовый поиск, статьи блога, система рекомендаций товара, веб-сайт в целом — ситуацию не изменяет. Все равно у вас нет интернет-магазина.
Очень хороший пример. Правда не совсем полный. То что работает веб-сайт в целом изменяет ситуацию с точки зрения падения в поисковой выдаче. Магазин может не продавать и падать в выдаче. А может не продавать и оставаться в выдаче на том же месте, если лежит частично, а не полность.
Слово «неключевым» заметили?

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

А вот если монолит падает, то в лучшем случае какая-то 500-я будет и работать не будет ничего. Естественно я о фатальных отказах, приводящих к сегфолтам, а то и паникам, в лучшем случае к выходу из процесса с ошибкой, а не о логических на уровне модулей.

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

Формально — да, как бы работает.

Но от простого просмотра каталога до реального заказа доходит хорошо если 1 из 1000.
Так что падение каталога — это фатально.

Слово «неключевым» заметили?


Да и привел пример, когда «неключевых» мало.
Их всегда мало, если сервис специализируется на одной услуге.
Не так фатально как для монолита. Хотя бы с саппортом можно початиться, получит эстимейты нормализации работы
Селективный деплой (не путать с горячей заменой модулей!) без проблем делается и в монолите, если заранее заложить его в архитектуру. Пишу как разработчик как раз такой архитектуры в нескольких проектах. Ничего сложного тут нет, надо лишь выделить ядро, и продумать интерфейсы для взаимодействия модулей — то же самое, что пришлось бы делать и в микросервисах, но чуть проще. При старте сканируется папка bin, из нее загружаются все библиотеки и скармливаются IoC-контейнеру.
Если монолит целиком переписать и потом его тестировать — то ну его нафиг, так вообще не полетит.

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

С чего бы это? Когда тестим монолит тестим сразу все, а если протестировали сервис, то нет гарантий, что он нормально интегрирован с окружением. Тестировать сервис сложнее, хоты бы потому, что окружение сложнее.
UFO just landed and posted this here

Так. Стоп. То есть юнит тесты на пакет/класс в коде вас не устраивают, а вот если вынести это в отдельное приложение и сделать такие же тесты, то все магически меняется?
Великолепная логика

UFO just landed and posted this here
Скорее речь о тестах, требующих запуск полноценного процесса в полноценном окружении, с разворачиванием хранилищ и моков внешних сервисов типа платежных систем.
Тестировать сервис проще. Тестировать систему сложнее.
Даже сервис тестировать сложнее, чем модуль внутри монолита, решающий те же задачи.
Вот не факт. Пример: для теста нужна БД, для монолита вам надо создать 500 табличек, для сервиса пускай 10.
Пример: для теста нужна БД

Для теста модуля монолита БД может быть не нужна совсем. Или нужна, но те же 10 табличек. Сервису же для тестов в любом случае надо базу и сетевого клиента.
Если для тестов модуля монолита нужны все 500 таблиц, то он плохо спроектирован. Такой же по качеству микросервис также захочет 500 таблиц из базы, которую будет делить еще с 50 микросервисами.

Для теста ни база, ни сетевой клиент не нужен.
Микросервис байдизайн должен иметь выделенную базу, ну или не иметь базы совсем.
Обязательно ли микросервису иметь выделенную БД, что бы называться микросервисом? Если у меня два, как я их называю, микросервиса, используют одну БД, то как они называются?
К примеру, один из них отвечает за регистрацию/авторизацию, а другой за обработку платежей
В общем случае это не микросервисы. Если обработке платежей нужны данные пользователей, то она должна лезть за ними в микросервис пользователей, а не в общую с ним базу.
И всё-таки, тогда как обозвать используемый мной подход?
Практика-то довольно распространённая. Есть несколько бэкендеров, у них разная зона ответственности, поэтому они на каждую предметную область заводят свой репозиторий, используя при этом одну БД.
У этого же есть какое-то название? Почему это не может быть микросервисом?
микросервисы это тоже SOA
микросервисы это тоже SOA

Для 2-х SOA-компонентов вам не нужна оркестрация.
Нужна. Другое дело, что она может быть и ручной. Собственно и для 100 она может быть ручной.
Смотря какие требования к ним предъявляются. Даже с двумя компонентами иметь автоматический скейлинг, роллинг апдейты и прочие ништяки вполне себе повод оркестратор какой-то поставить. Заодно проще развиваться будет дальше.
Наверное, можно назвать это микросервисами, если процессы разных модулей шарят одну базу данных, но об этом не догадываются. Если процесс обработки платежей не лезет в таблицы пользователей, чтобы вывести в квитанцию имя плательщика, а или хранит их абсолютно независимо, либо получает от сервиса регистрации/авторизации через сетевое (обічно) обращение.
Монолит просто стартовать не должен в общем случае при 10 табличках в базе, если он ждёт 500. Или должен но производить разворачивание базы. Ну просто нет базы начинает накатывать миграции. Или для каждого теста писать свои миграции?
Или для каждого теста писать свои миграции?

По логике, микросервис не должен лезть в чужие базы. Миграции у него должны быть свои, согласованные с версией этого микросервиса.
Я про тестирование монолита из 50 модулей по 10 таблиц на каждый (часто с foreign key между модулями, но замнём). Как в такой ситуации его тестировать? Общий поток миграций накатывать? Привязывать миграции к модулям? Ручками или костылями привязывать к тесту собственные миграции, синхронизируя с обычными? Копировать часть схему из эталонной базы?
Ничего, что речь шла о тестирование модуля монолита, умеющего то же, что и один микросервис?
Если каждый модуль нуждается в той же базе, что и монолит в целом, проблема не монолитности, а в качестве проектирования.
Каждый модуль нуждается в своих 10 табличках, но для тестирования модуля нужно запустить монолит, который нуждается в в 500 табличках всех модулей, ведь он монолит — или всё или ничего.

Я не знаю, зачем вам для тестирования одного конкретного модуля надо запускать монолит целиком.
Модульность затем и нужна, чтобы разрабатывать и тестировать модули можно было независимо.

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

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

Модуль — это просто кусок кода, с торчащими наружу функциями или классами.

Вытащить из монолита модуль — на порядок более простая задача, нежели вытащить из него модуль и сформировать микросервис. Поэтому говорить «вырезать из монолита микросервис для целей тестирования» — некорректно.
Понятно. Мы о разных модулях говорим. Я о тех модулях, которые рисуются на функциональных схемах систем, типа «модуль управления пользовтаелями и авторизации», «модуль учёта склада» и т. п. Такой модуль пронизывает систему через все слои.

Есть один процесс и это монолит.
А вот бинарных фалов с модулями может быть сколько угодно.
Еще в MS DOS были оверлеи.
В Windows появились dll.
В Linux также есть свои подгружаемые в один процесс бинарники.
Единственный бинарник на процесс в наше время экзотика.

Ох, извиняюсь, прочел то, что хотел видеть, подразумевая микросервисы.

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

И его так же можно делать тестирование, без остальных модулей («монолита»).
Это будет уже не совсем монолит, ведь таким путём можно дойти и до одного бинарника вроде монолитного, но список модулей (в пределе только из одного) берущего из конфига, а если в ходе работы вызывается какой-то не подключенный модуль, то ищущий среди своих инстансов тот, где он подключен, и дергающий его по сети. Это ещё будет монолитом? )
Использование IoC-контейнеров (которые позволяют динамическую конфигурацию) — это довольно распространенная практика для монолитов. Системы плагинов и динамически загружаемые библиотеки — тоже не новый революционный подход. Это требование SRP.

ищущий среди своих инстансов тот, где он подключен, и дергающий его по сети

Если есть сетевое взаимодействие между инстансами, это уже не монолит.
Зачем дергать по сети то, что можно загрузить в память и вызвать напрямую? Интерфейс известен заранее.

Это ещё будет монолитом?

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

Вообще спор монолит вс микросервисы больше просто обсуждение где остановиться в декомпозиции, а не плюсы или минусы декомпозиции в целом поскольку настоящих монолитов, не обращающихся по сети или локальным сокетам к сторонним процессам, очень мало осталось, по-моему. N-звенная архитектура, выделенная СУБД — уже не монолит, запускаемая по расписанию в отдельном процессе задача пускай того же бинарника — тоже.

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

Когда-то почти перестали писать реально монолитные приложения, выделяя из них сервисы, а часто не выделяя, а удаляя из них «наколенке» реализованную функциональность и вместо неё подключая сторонний сервер типа веб-сервера или СУБД — а это уже сервисно-ориентированная архитектура. Микросервисная — лишь дальнейшее разбитие, начавшееся в тот момент, скорее всего, когда кто-то решил «а давайте СУБД у нас будет отдельным сервисом» или «а давайте UI вынесем в отдельный сервис». После этого уже не стало монолитов а спор монолит вс микросервисы превращается в спор о том, нужно ли один большой самописный сервис («монолитный» апп-сервер, бесполезный без кучи других сервисов) дальше разбивать на более мелкие сервисы или пора остановится.
Вот я более чем уверен, что подавляющее большинство в этом топике говоря о монолите, например, в вебе, имеют в виду что-то вроде: клиент в браузере, веб-сервер, апп-сервер, СУБД, какой-нибудь редис, скорее всего где-то крон в фоне, может даже очередь с воркерами отдельными. Отдельная система анализа логов и мониторинга, автоматического перезапуска при краше. И про всё это говорят «у нас монолит». При это ещё прикладывая усилия для того, чтобы части апп-сервера минимально зависели друг от друга, обновлялись на лету, не загружались пока не нужны и выгружались когда уже не нужны.

Не совсем так. Это не мы говорим "у нас монолит", это приходит фанатик микросервисов и говорит "у вас не микросервисная архитектура? Значит, у вас ужасный монолит!"

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

Не скажу за всех, но я под этим подразумеваю, что бизнес-логика приложения не размазана по независимым приложениям. Интерфейсы занимаются вводом/выводом, БД — хранит состояние, кэши — прозрачно кэшируют.

Настоящих монолитов мало, как и настоящих микросервисных систем. Зато полно гибридов с массивными кусками, как-либо между собой интегрированными.

Берем и суем вместо обычного клиента БД собственный, возвращающий тестовые данные. В чем проблема?

это уже будет не тестирование монолита, а только какой-то его части.

По-моему, модульное тестирование всегда делают с подмененной БД, а e2e с настоящей. Ну а БД вообще не часть приложения.

Про модульное речи нет, там вообще без разницы если одни и те же принципы использованы. И не всегда без БД.

Значит вы про е2е тесты.
Там по-любому потребуется полная БД и все микросервисы/монолит. И опять с микросервисами сложнее.

Скорее про тесты конкретного HTTP API ендпоинта. В реальности подавляющее большинство запросов на него идёт из браузерного фронтенд-кода, но для этих тестов достаточно любого тестового http-клиента. То есть не полное тестирование системы, а только части серверного API.

Реализация конкретного API микросервиса может делать вызовы к другим микросервисам и для полноценного тестирования извольте поднимать весь оркестр.


А у модуля никакого WebAPI и тем более базы может вообще не быть. Достаточно обычных ООП-интерфейсов. У монолита WebAPI будут трогать только E2E-тесты.

Поднимать или мокать — отдельный разговор.

У модуля может быть любой API в том числе WebAPI, и база своя, ну или свои таблички в общей базе. Вот модуль аутенфикации и авторизации. Ему нужен свой ендпоинт, чтобы браузер или иной клиент стукнулся, ему нужна база, чтобы хранить юзеров, пароли, роли, права и связь этого всего друг с другом. Как вы будете тестировать авторизацию без WebAPI и базы? Как проверите, что, например, роутинг корректно настроен и объекты на базу корректно смаплены? и вообще всё это друг с другом связано. Это ещё не e2e с точки зрения всей истемы, потому что UI не задействован, но это тест WebAPI. Грубо, после его прохождения бэкендера можно на другой модуль или проект переводить, а не ждать пока фронтендеры что-то сделают.

Модулю не нужен EndPoint для браузера.
Модулю не нужна база.
Модулю ничего не нужно, кроме двух списков контрактов:


  1. То, что модуль обязуется реализовать.
  2. Необходимые модулю для обеспечения пункта 1

Есть модули, которые специализированы на доступе к базе или реализации внешних точек доступа. Но для модулей, в отличие от микросервисов, это экзотика.
Например, модуль авторизации 100% будет отвязан как от конкретной точки доступа, так и от конкретного хранилища данных.

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

Двумя сообщениями выше:


Даже сервис тестировать сложнее, чем модуль внутри монолита, решающий те же задачи.

Не надо сравнивать тестирование монолита целиком и одного микросервиса.
Один микросервис есть смысл сравнивать с одним из модулей монолита.

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

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

Вот как модулю авторизации не работать с базой юзеров? Ещё раз, мы обсуждаем эквивалентное тестирование микросервиса по сравнению с эквивалентным модулем монолита. Это значит, что если у микросервиса есть ендпоинт и база, значит и у модуля есть. Если на тесте микросервиса мы проверяем весь флоу от отработки сетевого запроса от клиента до работы с базой, значит и для модуля мы проверяем то же. Мокаете работу с базой при тестировании модуля авторизации — мокайте её и при тестировании микросервиса. Не делаете реальный http-запрос при тестировании модуля, а стучитесь к роутингу как-то напрямую — не делайте его и при тестировании микросервиса, только в нём роутинга можте не быть вообще :)
Вот как модулю авторизации не работать с базой юзеров

Очень просто: модулю авторизации хватит и абстракции над хранилищем.


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

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


Не делаете реальный http-запрос при тестировании модуля, а стучитесь к роутингу как-то напрямую — не делайте его и при тестировании микросервиса

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

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

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

Не хватит ему абстракции.

Еще как хватит. У монолита снаружи видно то, что у микросервисов есть в API Gateway.
Все остальные API внутрипроцессные.
С базой все точно также — бывают модули, требующие себе базу и таблицы, но в отличие от микросервисов, это тоже экзотика.


Почему вы предлагаете одну и ту же бизнес-функциональность тестировать по разному?

Потому что микросервис и модуль в составе монолита — это разные вещи.
В случае монолита у нас будут


  1. Модульные тесты на классы
  2. Интеграционные тесты на модуль
  3. End2End тесты на приложение

Для микросервиса c той же функциональностью:


  1. Модульные тесты на классы.
  2. Интеграционные тесты на модуль.
  3. Интеграционные тесты на микросервис.
  4. End2End тесты на приложение.
небольшой сервис тестить всяко легче монолита


Ну вы так же можете тестировать монолит всего лишь юнит-тестами.
Нет? Хотите интеграционные?
А почему с микросервисами не считаете нужным интеграционные?
Потому что это гораздо сложнее?

Мартин Фаулер хорошо разжевал что не все так просто
habr.com/post/261689

И ребята из Фланта
habr.com/company/flant/blog/427283

За все приходится платить.
В том числе и за видимую «простоту деплоя одного сервиса».

Серебряной пули так все еще и нет.
Где-то что-то имеет какие-то плюсы. Но имеет и минусы.
UFO just landed and posted this here
Нет. От того что функционал вынесен в отдельный сервис, не уменьшает количество тестов на этот функционал. При этом уже нужно писать интеграционные тесты.
UFO just landed and posted this here
Количество тестов у монолита > количества тестов у сервиса

А теперь возьмите сумму тестов всех микросервисов и сравните с количеством тестов монолита. Тесты пишутся на функционал, функционала при микросервисной архитектуры меньше не становится.

я клоню к тому, что в случае с микросервисами тестов меньше, и нагрузка на их содержание меньше, но нагрузка на инфраструктуру растет


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

Когда что-то в полноценном тесте всей системы пошло не так — разобраться, что виноват не ваш измененный микросервис, а косяк где-то в том (который вы вроде и не меняли), что вызывает тот, который вызывается тем, что вызывается из вашего — не проще.

Да, да, да. Это так же сложно выглядит при отладке как и сложно выглядит мое описание проблемы.
UFO just landed and posted this here

Что-то не спасают. Поэтому появились сервисы для трассировки.

логи спасут мир

Конечно, конечно.

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

И хорошо, если речь идет только об «линейно проходящих» запросах.

А если это фоновые процессы, запускаемые при разных условиях? Или если это несколько параллельно порожденных вызовов внутри микросервисной системы?

А если вам не хватит информации в логах? Добавить, сделав логи более подробными — не проблема. Но вам придется изменить и перезапустить некий третий микросервис только для того, чтобы отладить первый.

Никто не говорит, что в микросервисах невозможно отлаживать в принципе.

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

Когда вы переходите на микросервисы — сложность никуда не уходит.

Просто из монолита сложность размазывается между микросерисами и связями между ними.

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

У микросервисов есть свои преимущества. Которые являются недостатками в монолитах.

Но микросервисы вовсе не универсальная серебряная пуля. Так как появляются и новые недостатки. Которые в монолитах не так остры.

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

Вместо find usages и проверки всех использований вам надо каким-то образом при любом изменении бегать по графу зависимостей всех ваших сервисов, причём рекурсивно.

Ага, особенно хорошо тестировать End2End
UFO just landed and posted this here

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

Что мешает стараться писать код без прибивания гвоздями к библиотекам и вовремя их обновлять, история умалчивает.

Монолит — небольшой комок грязи(big ball of mud)

Так, всё-таки, большой или небольшой?
не тут как отрицание — большого комка грязи
тогда пробел нужен после «не»
Тут у вас отрицание не отдельного слова(небольшой = маленький), а всей фразы. Поэтому правильно писать с пробелом.
Пробела не хватает.
«Не большой кусок грязи». Чтобы программистам было понятнее: «не (большой кусок грязи (big ball of mud))». :-)

Главное не переезжать на микросервисы с количеством людей меньше микросервисов… ну вот решили мы сделать новый проект на микросервисах… всё красиво развернули, докер, куча баз, свежее апи, все дела, штук 10 сервисов пока. А разработчиков: один фиг 1-2 на бэке+сайт, плюс мобильщик, который так же должен заниматься своей частью бэка, если ему что-то нужно для мобилы по апи. И в итоге 80% времени чувак с сайта и мобильщик бессмысленно тратят время на понимание что идёт не так во всех этих микросервисах, которые намутил единственно разбирающийся в этом девопс. Ибо раньше они просто вставляли один метод в контроллер и всё, а теперь там 5 перекрестных вызовов между микросервисами, чтобы собрать все данные.

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

У сервиса должно быть понятное API — если нет, то это боль которая превращает наши сервисы еще в больший комок грязи.

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

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


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

Это не одно и то же, что и отличная спецификация (которая еще и постоянно меняется).

Тут проблема совсем в другом.

Ваш оппонент правильно сказал:

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

Но микросервисы — плохо когда разработчиков существенно меньше по количеству, чем микросервисов, так как на каждом из микросервисов идут дополнительные накладные расходы на создание и отладку, что при 1 разработчике на 10 микросервисов делает проект малоэффективным.

И это не решается сколь угодно точной спецификацией. Хотя бы посмотрите на отладку? Все уже написано по спецификации. На этапе отладки спецификация вам уже не поможет.

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

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

Монолит всегда дешевле поддерживать, каким бы он сложным не был, чем микросервисы. Микросервисы — это вынужденный архитектурный стиль для написания распределенных приложений, если нужно написать приложение, которое должно работать в облаке (cloud native), в других случаях нужно 200 раз подумать. Не нужно делать из монолита набор мельким монолитов и называть их микросервисами.
Монолит монолиту рознь. Монолит может быт на какойнить не очень популярной технологии которая досталась нам от внешнего вендора, плюс нужно учитывать такие факторы, как текучка, за пару лет на неочень преспективных проектах комнада может поменятся полностью и уже новая команда будет долго разбиратся с новым стеком и тогда стоимость потдержки будет расти.

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

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

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


нужно перепрлачивать за серверное железо

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

Монолит будет масштабировать дороже. Грубый пример: два модуля в монолите, каждый хочет по 8 Гб оперативы, работает на сервере на 16 Гб. Вдруг нагрузка на второй модуль увеличилась и решаем чтобы два инстанса его работали. Архитектура позволяет, масштабируемся на второй такой же сервер. Всё хорошо, но вот первый модуль теперь вхолостую жрёт 8 Гб, потому что он тоже отмасштабировался как часть монолита. А с микросервисами (точнее сервисами, необязательно микро) мы масштабируем только нужные модули. В нашем примере у нас сначала два сервера по 8 Гб, а потом 3 по 8Гб, а не сначала один на 16, а потом два на 16.
Лично я пишу на C++/Go и когда модуль который ничего не делает, но жрет 8Гб, то для меня это звучит как бага.

Вроде звучит как монолит на Java, но я видел монолиты на Java, которые не съедают все ресурсы сервера.
Я же написал «грубый пример». Придраться тут можно много к чему, это просто демонстрация идеи. Замените 8 на X, а 16 на 2X. X возьмите приемлемый для своих реалий.
Давайте будем реалистами. Ничто из ниоткуда не берется.
А кто говорит про «ниоткуда»? Разбиение монолита на сервисную архитектуру не бесплатно и для разработчиков, и для эксплуатации.
А кто говорит про «ниоткуда»?

Вы:


два модуля в монолите, каждый хочет по 8

Сервис ничего не делает, но уже съел память. Уход на X и 2X ничего не меняет. Может быть вы приведёте реальный пример, где такое потребление ресурсов, это не архитектурная ошибка.

Прогрев внутренних кэшей принудительный. Причём поскольку монолит, то или всё, или ничего
Давайте приведу пример из жизни. PostgreSQL— это типичный монолит. Я могу запустить его на 1 core 512mb, так и на 64 core 512Gb. Все потому, что разработчики не стали харкодить параметры, а вынесли в конфиг. Соответственно, если вынести настройку компонентов в конфиг, то можно запускать только то, что нужно.
PostgreSQL — это типичный пример сервис-ориентированной архитектуры. Посмотрите сколько разных исполняемых бинарников в нём. Сколько разных процессов крутится.

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

Я не процессы и потоки вообще, а про специализированные процессы решающие узкие задачи во взаимодействии с другими.

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

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

А куча сетевых запросов с сериализацией/десериализацией ресурсы не тратит?

золотые слова, присоединяюсь
Микросервисы — это вынужденный архитектурный стиль для написания распределенных приложений, если нужно написать приложение, которое должно работать в облаке (cloud native), в других случаях нужно 200 раз подумать


Вы вполне можете запускать монолит в облаке.

Разумеется, монолит должен изначально поддерживать совместную работу множества инстансов.

Серьезные монолиты (у того же Фейсбука), разумеется, живут не на одном единственном сервере.

Ещё один аспект — микросервисы позволяют использовать GPL код совместно с вашим закрытым.

С такой стороный не смотрел на эту проблему, но это могло бы работать в идельном мире. Но таже Vmware не публикует свой код в GPL, а сколько небольших компаний юзают либы и не публикуют свой код.

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

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

Монолиты так же живут хорошо в облаках

Я это и не опровергаю.

а Микросервисы это не вынужденный архитектурный стиль, микросервисы хорошо масштабируются

Вот поэтому они хорошо и маштабируются. Мы вынуждены придерживаться определенного архитектурного подхода, чтобы это обеспечить, поэтому Микросервисы — это вынужденый архитектурный стиль ИМХО.

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

Да кто про это говорит? Я же говорю, что если приняли решение идти в облоко, то микросервисы и еще 200 раз подумайте. Я не к тому, что если облоко, то 100% микросервисы, совсем нет.

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

Монолиты так же живут хорошо в облаках

Я это и не опровергаю.

а Микросервисы это не вынужденный архитектурный стиль, микросервисы хорошо масштабируются

Вот поэтому они хорошо и маштабируются. Мы вынуждены придерживаться определенного архитектурного подхода, чтобы это обеспечить, поэтому Микросервисы — это вынужденый архитектурный стиль ИМХО.

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

Да кто про это говорит? Я же говорю, что если приняли решение идти в облоко, то микросервисы и еще 200 раз подумайте. Я не к тому, что если облоко, то 100% микросервисы, совсем нет.

Пока вы не распространяете свой закрытый код, вы можете монолитно (статически) линковать его с GPL кодом. Иначе нужно использовать динамическую линковку (dll), где все gpl модули вынесены в отдельные файлы dll.
>Микросервисы добавляют сложность
Они её ни добавляют ни уменьшают. Сложность перераспределятся с уровня кода и его архитектуры, на уровень инфраструктуры. В итоге часть работы снимается с одних людей и ложится на других.

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

На уровне ифраструктуры это как раз перераспределение.
На уровне кода это одно и тоже, если код нормально написан и протокол взаимодействия устаканился.


Если уже написан и отлажен — да.
А ошибки сети, а балансировка? Как это все отлаживается — неужели нет разницы?
Балансировка — это инфраструктура. Обработка ошибок сети реализуется один раз (или один раз на каждый ЯП).
Обработка ошибок сети реализуется один раз


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

Вы как-то слишком упрощаете.

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

Но в таком случае вы теряете много контроля над процессом.

>если логика задачи требует повторных попыток?
То они были бы и без микросервиса.

>инициализация соединения/авторизация в соединении, зачем это делать каждый раз?
И действительно, зачем? Достаточно одного раза, в чём проблема? Не надо в каждом месте вызова соединение создавать.

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

То они были бы и без микросервиса.


Внутренние вызовы не в пример надежнее, чем внешние RPC.
>Внутренние вызовы не в пример надежнее, чем внешние RPC.
Но это не значит, что их ошибки можно не обрабатывать. Всё равно надо. Какая разница, как часто фейлится логика: 1 из 1000, или 1 из 1000000. На больших числах ошибки всё равно будут.

Внутренние это на одном железе которые?

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

Вот микросервисы, кстати, ещё можно так разворачивать — код + небольшая база (и то спорный вопрос).

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

Я думаю, большинство людей всё-таки имеет в виду более широкую трактовку.
Скорее более узкую: монолитом называют не всю систему, а некоторую её часть типа апп-сервера, да и то забывая про то, что иногда тот же бинарник запускается с другими ключиками в отдельном процессе и выполняет совсем другую работу по сравнению с основным процессом.
Достаточно одного раза, в чём проблема?


В сетевой микросервисной среде у вас априори более слабые возможности по контролю прохождения вызовов.

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

Код инициалиазции, переподключения, обработки ошибок содинения пишется один раз.

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

Для примера: в монолите пишется код для обработки ошибок при работе с базой, в микросервисной архитектуре — для ошибок при работе с сервисами. Частота ошибок может быть разная, но код писать всё равно надо и во многих случаях он выглядеть будет одинаково.
если логика задачи требует повторных попыток?
То они были бы и без микросервиса.

Не были бы. В монолите была бы вызвана функция и все. В микроскопическое надо учитывать, что ваш сервис может рестартовать. В каждом случае прийдется решать отдельно как делать повторные вызовы: сколько ждать, сколько раз повторять, нужно ли вообще что-то делать если это ошибка DNS и т.п.

UFO just landed and posted this here
Для сложно проекта это о-маленькое от необходимых решений при анализе кода. Эти вопросы и так везде стоят. Есть же базы, кэши, отложенные задачи, внешние сервисы какие-то. В случае работы с ними, те же самые вопросы встают при каждом обращении.

Для большинства случаев достаточно выработать соглашение в проекте по стандартному поведению в случае ошибок и закрепить его в коде. Это делается 1 раз.

Для особых случаев всегда приходится применять особые меры и решения, безотносительно того есть там обращение к микросервисам или нет его.

И само собой, микросервис — не серебрянная пуля. Если он реально мешает в каком-то частном случае, то не надо этот микросервис выделять.

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

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

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


Blue-green deployment это называется.
С монолитами вы тоже можете это делать. Точно так же.
Постойте, а как же resume-driven architecture?
Как она строится?
Применяем ту, которая хорошо будет смотреться в резюме при следующем поиске работы. Поиск работы планируем сразу после ввода в эксплуатацию, поддержка и развитие — не царское дело :)
А если система здоровая или проект долгий — то можно и не дождаться ввода
Можно не дожидаться :)
Микросервисы это хорошо… когда они «микро» и реально изолированы друг от друга

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

… а так и кусок вполне ощутимого по размерам монолита вполне может являться микросервисом для других приложений — по сути это все публичные API крупных интернет-компаний (метрики, картография итп), с тем лишь исключением что их работа — не совсем собственная забота
Из тех проектов, что я видел, часто с помощью «микросервисности» пытаются решить проблемы «монолита», которые обычно возникают от недостатка «дисциплины» и/или «осознанности» в разработке архитектуры.
Главное в этом деле — сменить работу раньше чем компания столкнется с последствием твоего решения. Тогда можно будет на митапах бодро рассказывать как внедрил микросервисную архитектуру, пока ищешь новую жертву.

Два чая этому господину. Вот так взяли и структурированно и понятно описали именно то, что мне каждый раз приходит в голову, когда слышу очередные истории успеха от адептов микросервисов. Единственный вменяемый аргумент это возможность проще скейлится и делать это динамически + нет привязки к одному стеку company wide. Но это плюсы, которые действительно полезны на большом масштабе, а не в проекте уровня CRM система на заводе

Единственный вменяемый аргумент это возможность проще скейлится и делать это динамически + нет привязки к одному стеку company wide.


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

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

Полностью согласен. Это вопрос масштаба исключительно

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

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

Для «поделить работу» микросервисы не нужны. Совсем.
Они могут для этого использоваться, но это, насколько я знаю, не их целевое назначение.
Самая большая боль, как по мне, так это развертывание всей этой карусели на локальной тачке. Допустим, часть сервисов крутится на стейджинге, а для разработки нужно поднять только часть из них: и начинается переписывание конфигов каждого из сервисов, чтоб они смотрели друг на друга.
Это занимает много времени и порождает желание написать свои костыли в виде каких-то генераторов конфигов.
Вот как вы живете с этим? Может есть таблетка от этого?
Если они очень часто смотрят друг на друга — возможно, в архитектуре надо что-то исправить.
Разве minikube не для этого придуман? А ежели сервисы настолько переплетены, что для разработки нужно поднять почти их все, то наверное действительно надо в архитектуре что-то исправить.
А ежели сервисы настолько переплетены, что для разработки нужно поднять почти их все, то наверное действительно надо в архитектуре что-то исправить.


В логике бизнес-задачи это может быть изначальным.

Если основная цель вашего проекта — оказание одной-единственной основной услуги и вы проводите проверку функционала этой самой основной услуги, например.

Тогда все большая часть модулей вашего проекта направлены именно на это.

Ибо зачем вы остальные-то модуля писали вообще, если без них можно обойтись?

Пример интернет-магазина habr.com/company/raiffeisenbank/blog/427953/#comment_19310299
Не так уж много частей не задействовано, если мы проверяем ключевую операцию для такого проекта — как протекает оформление товара в целом.

Миникуб или локальный докер (сварм) придуманы для этого, но в сложных проектах их недостаточно, банально не хватает ресурсов даже на мощной дев-машине поднимать десятки сервисов у каждой из которых своя СУБД. Не БД, а СУБД — отдельный мастер-процесс.
У нас коллега запилил специальный докер контейнер, который запускаешь на локальной тачке и там вся инфраструктура со своими взаимосвзями живет (но только по одному сервису). Единственное, надо базу сидить после обновлений или миграций.
Когда нужен только один сервис локально, а остальные со стейджинга идут, то нормально разруливается с локальным .env файлом в корне сервиса для докера. Или сервисов немного или они легкие, то и просто запустить всё локально приемлемо.

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

Тут все забыли еще один существенный момент — кучка микросервисов сожрет вычислительных ресурсов заметно больше, чем монолит. Хотя бы на том, что при передаче запросов между микросервисами данные надо будет перевести из внутреннего бинарного представления во внешнее (xml/json/...), затем преобразовать их назад в бинарное, по дороге проверив корректность данных, права доступа и т.п. В монолите все это делается один раз, в микросервисе десятки, а то и сотни раз за цикл обработки одного запроса.
В монолите все это делается один раз, в микросервисе десятки, а то и сотни раз за цикл обработки одного запроса.


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

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

Чем получить систему более эффективно использующую железо, но позже.

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


Если компании по итогу не существует именно из-за технической ошибки, то коллектив там был сильный?
Это предсказуемые, даже очевидные минусы.
Видимо на столько очевидные, что ни в одной презентации от лидеров рынка про это ни слова. Ни в одной концепции развития у крупных заказчиков не видел. Обратное утверждение, про снижение числа вычислительных ресурсов иногда встречал.
У всех виденных мной расчет экономики строился как минимум на не увеличении серверного парка, тепла, места, числа сетевых интерфейсов…
Тут есть всего два варианта — либо уважаемые эксперты не в курсе очевидного минуса, либо они наглые обманщики. Выбор варианта по вкусу.

Википедия:


Архитектура постоянно подвергается критике с самого момента её формирования, среди новых проблем, которые возникают при её внедрении отмечаются:

сетевые задержки[5]: если в модулях, выполняющих несколько функций, взаимодействие локально, то микросервисная архитектура накладывает требование атомизации модулей и взаимодействия их по сети;

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


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

У Микрософт еще давным давно была реализована микросервисонсть на машине, в виде COM, дальнейшим развитием стал DCOM, все проблемы которые были там, в том или ином виде проявляются в микросервисной архитектуре.
Все новое, хорошо забытое старое.

COM/DCOM (вернее систему, построенную на базе этих интерфейсов) можно считать с натяжкой имплементацией, частным случаем сервисной архитектуры. И часть проблем COM/DCOM микросервисная архитектура решает чуть ли не определению микросервиса (некоторым из них :) ). Если так хочется считать COM/DCOM предком MSA, то это не хорошо забытое старое (тем более что оно активно продолжает использоваться), а переосмысленное и улучшенное, даже просто по теории: часть ограничений сняли, но ввели новые.

Sign up to leave a comment.