Основной посыл всех этих докладов — микросервисы помогают уйти от излишней сложности и запутанности проекта. Но, как по мне, от сложности не избавиться совсем, нельзя переделать проект, чтобы сразу всё стало просто. Сложность из одной области перейдет в другую.
Например: был очень сложный запутанный монолит, мы его разбили на несколько сервисов, каждый из них выглядит прекрасно, любой сможет разобраться с кодом, но что происходит с окружением? Сложность растет: это и распределенные транзакции, которые нужно журналировать так, чтобы понять, что это одна транзакция; для каждого сервиса прибавляется CI/CD и поставка; схема взаимодействия становится нетривиальной.
Самые спорные тезисы или утверждения, которые я слышал на докладах и с которыми я готов спорить:
Вход в проект монолита дороже для новых членов команды. Почему-то принято оценивать стоимость вхождения в проект по тому, как быстро новый разработчик начнёт делать задачи. Да, в маленьком сервисе он разберется очень быстро и задачу выдаст очень быстро (тем более по спецификации, «что написали, то я и сделал»).
Но как насчет других членов команды?
Новый тестировщик будет разбираться с интеграционной моделью. Протестировать сервис — это хорошо, но кроме тестирования контракта сервиса нужно проверить бизнес-процесс, который затрагивает несколько сервисов.
Новый аналитик на первых порах может вообще голову сломать, пока разберется во всех хитросплетениях внутренних вызовов.
Микросервисы позволяют чаще релизить. Микросервисы дорабатывать быстрее, потому что они разнесены на несколько параллельных задач, которые разрабатываются и тестируются параллельно, и остается только проверить интеграцию (без учета времени на аналитику).
С монолитом тоже можно так делать, всё зависит от декомпозиции задачи. Чаще всего в самом начале будет одна задача — сделать общую функциональность (общую БД подправить, или интерфейс доработать), а дальше каждый будет пилить свои подзадачи и отдавать их в тестирование.
И время выпуска фичи, за которую платит бизнес, будет одинаковое. Фича будет закрыта только когда будут выпущены все компоненты. Микросервисы могут решить 99% задач, но пока не закроется последняя фича, их не выпустят в бой.
О чем еще не говорят
Сложность растет
При использовании микросервисов усложняется инфраструктура. Это связано с тем, что нужно поддерживать работу не одного приложения, а множества сервисов. Нужно мониторить работоспособность всех сервисов, хорошо понимать зависимости сервисов по версиям, иметь CI/CD-планы для сборки сервисов и поставки, механизмы реагирования на выходы сервисов из строя, чтобы не легло всё остальное.
Вроде бы простые вещи, и в монолите мы должны делать всё то же самое. Только в монолите мы работаем над одним приложением, а с увеличением количества сервисов сложность растет, что требует от поддержки более высоких навыков.
Микросервисы добавляют сложность — новые библиотеки, новая функциональность для поддержки распределенных транзакций, для обработки ошибок других сервисов, отправки повторных запросов, отката транзакций. По большей части эти механизмы будут общими, и большинство разработчиков не полезут в «кишки», а будут только использовать их.
Но и в них могут быть ошибки, которые придётся чинить. Если с починкой мы справляемся без проблем, то чтобы раскатать изменения по 200—300 сервисам, понадобится время и развитые средства управления. А если понадобится пересобрать сервисы с обновленной библиотекой, а то и вызовы переделать (вот так починили, не предусмотрели), то всё это будет не весело.
Монолит — не большой комок грязи(big ball of mud)
Как обычно начинаются рассказы про прекрасный мир микросервисов? «Был у нас монолит, это был сплошной комок грязи, в котором всё запутанно и непонятно», плюс ещё картинку страшную покажут. И монолит уже стал чем-то пугающим, «будете плохо работать, ваш проект превратится в монолит». Но НЕТ.
Монолит может быть(и должен) понятным, структурированным, с ‘хорошим’ кодом, с документацией, как и микросервисный проект может превратиться в еще больший комок грязи, если не заниматься процессами разработки и не следить за качеством разработки.
Так что же использовать?
Хороший вопрос, и ответ можете дать только вы. Потому что только вам известно, какие проблемы бизнеса вы решаете, каким будет проект. Нет серебряной пули, нет идеальной архитектуры, которую можно использовать и будет всегда “счастье”.
И в монолите, и в микросервисах следите за документацией и поддерживайте её в актуальном состоянии. С документацией лучше, чем без неё.
Выстраивайте такой процесс разработки, при котором качество кода будет только расти (ревью, модульные тесты). Но про качество можно целую книгу написать, это тема для отдельного большого разговора.
Простой и понятный код — это не про микросервисы, код априори таким должен быть.
Автоматизация тестирования — это тоже про качество кода.
Автоматизируйте всё, что можно автоматизировать — CI/CD. Наверное, есть такой стек технологий, который очень трудно затянуть в CI/CD, но 99% сборок/поставок можно автоматизировать.
Комментарии (150)
inf
31.10.2018 08:37Монолит — небольшой комок грязи(big ball of mud)
Так, всё-таки, большой или небольшой?G1yyK Автор
31.10.2018 08:41+1не тут как отрицание — большого комка грязи
GennPen
31.10.2018 10:15Тут у вас отрицание не отдельного слова(небольшой = маленький), а всей фразы. Поэтому правильно писать с пробелом.
dedmagic
31.10.2018 10:17Пробела не хватает.
«Не большой кусок грязи». Чтобы программистам было понятнее: «не (большой кусок грязи (big ball of mud))». :-)
Marwin
31.10.2018 08:48+3Главное не переезжать на микросервисы с количеством людей меньше микросервисов… ну вот решили мы сделать новый проект на микросервисах… всё красиво развернули, докер, куча баз, свежее апи, все дела, штук 10 сервисов пока. А разработчиков: один фиг 1-2 на бэке+сайт, плюс мобильщик, который так же должен заниматься своей частью бэка, если ему что-то нужно для мобилы по апи. И в итоге 80% времени чувак с сайта и мобильщик бессмысленно тратят время на понимание что идёт не так во всех этих микросервисах, которые намутил единственно разбирающийся в этом девопс. Ибо раньше они просто вставляли один метод в контроллер и всё, а теперь там 5 перекрестных вызовов между микросервисами, чтобы собрать все данные.
G1yyK Автор
31.10.2018 08:59Тут наверное вопрос к спеке, микросервисы должны упрощать работу, если нужна информация по пользователю.
У сервиса должно быть понятное API — если нет, то это боль которая превращает наши сервисы еще в больший комок грязи.
И если мы интегрируемся с сервисами, мы должны знать только контракт и особо разбираться что там под капотом происходит нет смысла.
По поводу количества людей на проекте, думаю это не корректно — по человеку на сервис, небольшая команда может пилить и 100 сервисов, нужна только хорошая документация, выстроенный процесс. Сервисы не очень большие и после разработки все разом не очень часто меняются.stratosmi
31.10.2018 17:03+2Тут наверное вопрос к спеке, микросервисы должны упрощать работу, если нужна информация по пользователю.
Если вам вместо того, чтобы просто вызывать функцию…
… нужно сделать вызов по сети и отработать ситуацию с ошибками, возможно повторить через некоторое время и послать в этот раз запрос на другой экземпляр микросервиса — это несколько другой объем работы (не только по созданию, а еще и при отладке), чем просто вызывать функцию.
Это не одно и то же, что и отличная спецификация (которая еще и постоянно меняется).
Тут проблема совсем в другом.
Ваш оппонент правильно сказал:
Микросервисы отличный способ распределения задач между разработчиками, когда разработчиков очень много.
Но микросервисы — плохо когда разработчиков существенно меньше по количеству, чем микросервисов, так как на каждом из микросервисов идут дополнительные накладные расходы на создание и отладку, что при 1 разработчике на 10 микросервисов делает проект малоэффективным.
И это не решается сколь угодно точной спецификацией. Хотя бы посмотрите на отладку? Все уже написано по спецификации. На этапе отладки спецификация вам уже не поможет.
VolCh
31.10.2018 17:48Микросервисы не способ распределения задач между разработчиками или ещё какого упрощения нам жизни. Микросервисы способ решать проблемы эксплуатации: эффективное масштабирование, раздельный деплой, возможность частичной работоспособности и т. п.
Losted
31.10.2018 21:26+1На самом деле, сервисы могут быть в том числе и способом разделения ответственности между командами и, следовательно, могут влиять на распил задач. Но опять же, сложность никуда не уходит — она просто поднимается на уровень выше — на координацию команд, например, через спеки.
creker
31.10.2018 22:43В том числе и способ разделения, если послушать большие компании, которые на микросервисах сидят. У них офисы по всему миру, каждый пишет на своем языке, своем стэке. Микросервисы дают тут разделение ответственности, свободу выбору технологий, совместимость, т.к. у всех общий кроссплатформенный интерфейс. Правда со временем может прийти проблема, когда технологий разных слишком много, как и сервисов, и с этим сложно управляться. Об этом uber как-то рассказывал.
G1yyK Автор
31.10.2018 10:25Архитектура — это же ведь не только про компоновку компонентов, но и про развертывание, и про поддержку и тестирование. При выборе архитектуры нужно учитывать не только плюсы той или иной архитектуры, но и риски, и проблемы с которыми можем столкнутся и тп.
Если при проектировании были учтены все эти факторы и была выбрана подходящая архитектура для проекта, которая решает задачи проекта, то и поддержка, тестирование, разработка не будут вызывать боль.
ikirin
31.10.2018 10:45Монолит всегда дешевле поддерживать, каким бы он сложным не был, чем микросервисы. Микросервисы — это вынужденный архитектурный стиль для написания распределенных приложений, если нужно написать приложение, которое должно работать в облаке (cloud native), в других случаях нужно 200 раз подумать. Не нужно делать из монолита набор мельким монолитов и называть их микросервисами.
G1yyK Автор
31.10.2018 10:57-1Монолит монолиту рознь. Монолит может быт на какойнить не очень популярной технологии которая досталась нам от внешнего вендора, плюс нужно учитывать такие факторы, как текучка, за пару лет на неочень преспективных проектах комнада может поменятся полностью и уже новая команда будет долго разбиратся с новым стеком и тогда стоимость потдержки будет расти.
Монолиты так же живут хорошо в облаках, ток стоит это других денег, а Микросервисы это не вынужденый архитектурный стиль, микросервисы хорошо маштабируются и не нужно перепрлачивать за серверное железо, позволяют более грамотно утилизировать ресурсы.(это частный случай)
А про облака и тп — это наверное уже про стоимость владения, которая складывается не только из поддержки, но сервера, лицензии и обновления — и это может быть дороже чем содержать команду и расчитывается она не на один год, а на период(года).RPG18
31.10.2018 11:41микросервисы хорошо маштабируются и не нужно перепрлачивать за серверное железо
Лукавите. Что бы наносервис, микросервис, да вообще любой сервис масштабирование, нужно масштабирование заложить в архитектуру. Если это не закладывается, то и микросервис невозможно будет от масштабировать. Если это заложить в монолите, то и монолит можно будет хорошо масштабировать.
нужно перепрлачивать за серверное железо
Переплата происходит в случае вертикального масштабирования. Если же при горизонтальном масштабировании не нагруженный монолит потребляет куча ресурсов, то это косяк разработчиков, которые не занимаются оптимизацией.
VolCh
31.10.2018 17:56-3Монолит будет масштабировать дороже. Грубый пример: два модуля в монолите, каждый хочет по 8 Гб оперативы, работает на сервере на 16 Гб. Вдруг нагрузка на второй модуль увеличилась и решаем чтобы два инстанса его работали. Архитектура позволяет, масштабируемся на второй такой же сервер. Всё хорошо, но вот первый модуль теперь вхолостую жрёт 8 Гб, потому что он тоже отмасштабировался как часть монолита. А с микросервисами (точнее сервисами, необязательно микро) мы масштабируем только нужные модули. В нашем примере у нас сначала два сервера по 8 Гб, а потом 3 по 8Гб, а не сначала один на 16, а потом два на 16.
RPG18
31.10.2018 18:05+1Лично я пишу на C++/Go и когда модуль который ничего не делает, но жрет 8Гб, то для меня это звучит как бага.
Вроде звучит как монолит на Java, но я видел монолиты на Java, которые не съедают все ресурсы сервера.VolCh
31.10.2018 18:13Я же написал «грубый пример». Придраться тут можно много к чему, это просто демонстрация идеи. Замените 8 на X, а 16 на 2X. X возьмите приемлемый для своих реалий.
RPG18
31.10.2018 18:18-1Давайте будем реалистами. Ничто из ниоткуда не берется.
VolCh
31.10.2018 18:21А кто говорит про «ниоткуда»? Разбиение монолита на сервисную архитектуру не бесплатно и для разработчиков, и для эксплуатации.
RPG18
31.10.2018 18:43+2А кто говорит про «ниоткуда»?
Вы:
два модуля в монолите, каждый хочет по 8
Сервис ничего не делает, но уже съел память. Уход на X и 2X ничего не меняет. Может быть вы приведёте реальный пример, где такое потребление ресурсов, это не архитектурная ошибка.
VolCh
31.10.2018 23:37Прогрев внутренних кэшей принудительный. Причём поскольку монолит, то или всё, или ничего
RPG18
01.11.2018 14:22Давайте приведу пример из жизни. PostgreSQL— это типичный монолит. Я могу запустить его на 1 core 512mb, так и на 64 core 512Gb. Все потому, что разработчики не стали харкодить параметры, а вынесли в конфиг. Соответственно, если вынести настройку компонентов в конфиг, то можно запускать только то, что нужно.
VolCh
01.11.2018 15:22PostgreSQL — это типичный пример сервис-ориентированной архитектуры. Посмотрите сколько разных исполняемых бинарников в нём. Сколько разных процессов крутится.
Я вообще не понимаю о чём мы тут спорим? Что нельзя сэкономить на ресурсах перейдя на микросервисную архитектуру и масштабируя только отдельные модули? Или что идеальный монлит можно превратить в набор микросервисов через конфиги?
bo0rsh201
31.10.2018 22:48Единственное, в чем будет разница по памяти между запущенным инстансом монолита и микросервиса, которые делают одно и то же — это в размере бинарника. Именно на эту разницу и увеличится потребление памяти. Память стоит копейки. Ради того, чтобы ее сэкономить вы чудовищно усложняете разработку и поддержку, вводите кучу сущностей, процессов и инструментов, а это как раз стоит дорого.
Как вам вообще удаётся бизнесу продавать такие вещи?VolCh
31.10.2018 23:39Не понимаю как у вас так получится. Даже если ленивая инициализация модулей, то структуры для ленивой инициализации надо заранее готовить.
stratosmi
31.10.2018 16:39Микросервисы — это вынужденный архитектурный стиль для написания распределенных приложений, если нужно написать приложение, которое должно работать в облаке (cloud native), в других случаях нужно 200 раз подумать
Вы вполне можете запускать монолит в облаке.
Разумеется, монолит должен изначально поддерживать совместную работу множества инстансов.
Серьезные монолиты (у того же Фейсбука), разумеется, живут не на одном единственном сервере.
jaiprakash
31.10.2018 11:04+1Ещё один аспект — микросервисы позволяют использовать GPL код совместно с вашим закрытым.
G1yyK Автор
31.10.2018 11:20-1С такой стороный не смотрел на эту проблему, но это могло бы работать в идельном мире. Но таже Vmware не публикует свой код в GPL, а сколько небольших компаний юзают либы и не публикуют свой код.
Там все не просто с лицензиями..., мысль отличная, нужно подумать над ней. Но в риалиях современного мира, я видел когда софт в оборонку поставляется с нарушением лицензий, в военских частях стоят откровенной пиратский софт.
ikirin
31.10.2018 11:27С микросервисами могут случиться (и обязательно случиться) те же неприятности, что и с монолитом — устарел стэк технологий и т.д. и тому подобное. Поэтому сравнивают при всех равных и получается, что монолит всегда проще и в производстве и в поддержке.
Монолиты так же живут хорошо в облаках
Я это и не опровергаю.
а Микросервисы это не вынужденный архитектурный стиль, микросервисы хорошо масштабируются
Вот поэтому они хорошо и маштабируются. Мы вынуждены придерживаться определенного архитектурного подхода, чтобы это обеспечить, поэтому Микросервисы — это вынужденый архитектурный стиль ИМХО.
А про облака и тп — это наверное уже про стоимость владения, которая складывается не только из поддержки, но сервера, лицензии и обновления
Да кто про это говорит? Я же говорю, что если приняли решение идти в облоко, то микросервисы и еще 200 раз подумайте. Я не к тому, что если облоко, то 100% микросервисы, совсем нет.
ikirin
31.10.2018 11:26С микросервисами могут случиться (и обязательно случиться) те же неприятности, что и с монолитом — устарел стэк технологий и т.д. и тому подобное. Поэтому сравнивают при всех равных и получается, что монолит всегда проще и в производстве и в поддержке.
Монолиты так же живут хорошо в облаках
Я это и не опровергаю.
а Микросервисы это не вынужденный архитектурный стиль, микросервисы хорошо масштабируются
Вот поэтому они хорошо и маштабируются. Мы вынуждены придерживаться определенного архитектурного подхода, чтобы это обеспечить, поэтому Микросервисы — это вынужденый архитектурный стиль ИМХО.
А про облака и тп — это наверное уже про стоимость владения, которая складывается не только из поддержки, но сервера, лицензии и обновления
Да кто про это говорит? Я же говорю, что если приняли решение идти в облоко, то микросервисы и еще 200 раз подумайте. Я не к тому, что если облоко, то 100% микросервисы, совсем нет.
vanxant
31.10.2018 11:33+1Пока вы не распространяете свой закрытый код, вы можете монолитно (статически) линковать его с GPL кодом. Иначе нужно использовать динамическую линковку (dll), где все gpl модули вынесены в отдельные файлы dll.
Tiendil
31.10.2018 13:05>Микросервисы добавляют сложность
Они её ни добавляют ни уменьшают. Сложность перераспределятся с уровня кода и его архитектуры, на уровень инфраструктуры. В итоге часть работы снимается с одних людей и ложится на других.
В одних случаях это хорошо, в других — плохо.VolCh
31.10.2018 18:05+1Всё же добавляют. Как не крути, но локальный вызов процедуры внутри процесса проще удаленного вызова и на уровне инфраструктуры, и на уровне кода.
Tiendil
31.10.2018 18:45+2На уровне кода это одно и тоже, если код нормально написан и протокол взаимодействия устаканился. Для примера можно взять кучу библиотек для генерации клиентов rest api для любых языков.
На уровне ифраструктуры это как раз перераспределение.stratosmi
31.10.2018 19:22На уровне кода это одно и тоже, если код нормально написан и протокол взаимодействия устаканился.
Если уже написан и отлажен — да.
А ошибки сети, а балансировка? Как это все отлаживается — неужели нет разницы?Tiendil
31.10.2018 19:36Балансировка — это инфраструктура. Обработка ошибок сети реализуется один раз (или один раз на каждый ЯП).
stratosmi
31.10.2018 20:10Обработка ошибок сети реализуется один раз
Почему?
А если логика задачи требует повторных попыток?
А инициализация соединения/авторизация в соединении, зачем это делать каждый раз?
И пр.
Вы как-то слишком упрощаете.
Конечно можно реализовать так, чтобы вызов удаленного микросервиса выглядел как вызов процедуры.
Но в таком случае вы теряете много контроля над процессом.
Tiendil
01.11.2018 09:57>если логика задачи требует повторных попыток?
То они были бы и без микросервиса.
>инициализация соединения/авторизация в соединении, зачем это делать каждый раз?
И действительно, зачем? Достаточно одного раза, в чём проблема? Не надо в каждом месте вызова соединение создавать.
>можно реализовать так, чтобы вызов удаленного микросервиса выглядел как вызов процедуры.
Я не это предлагаю. Выглядеть он должен как вызов микросервиса. Но сил программиста на написание этого вызова можно тратить столько же, сколько и на вызов локального кода.
stratosmi
01.11.2018 11:22То они были бы и без микросервиса.
Внутренние вызовы не в пример надежнее, чем внешние RPC.Tiendil
01.11.2018 12:00-1>Внутренние вызовы не в пример надежнее, чем внешние RPC.
Но это не значит, что их ошибки можно не обрабатывать. Всё равно надо. Какая разница, как часто фейлится логика: 1 из 1000, или 1 из 1000000. На больших числах ошибки всё равно будут.
Внутренние это на одном железе которые?
Это довольно простой случай. Та же база далеко не всегда находится на том же железе, что и работающий с ней код. Коду нужны одни параметры железок, базе — другие.
Вот микросервисы, кстати, ещё можно так разворачивать — код + небольшая база (и то спорный вопрос).
VolCh
01.11.2018 12:19В академическом смысле, если у нас есть отдельная база, то уже не монолитный сервис, а распределенная сервисная архитектура типа есть сервис основной логики и сервис хранения. По сути сетевая СУБД это микросервис, ну пускай сервис.
Tiendil
01.11.2018 13:00Да. Но в такой трактовке область применения монолитной архитектуры слишком сужается.
Я думаю, большинство людей всё-таки имеет в виду более широкую трактовку.VolCh
01.11.2018 13:18+1Скорее более узкую: монолитом называют не всю систему, а некоторую её часть типа апп-сервера, да и то забывая про то, что иногда тот же бинарник запускается с другими ключиками в отдельном процессе и выполняет совсем другую работу по сравнению с основным процессом.
stratosmi
01.11.2018 11:24Достаточно одного раза, в чём проблема?
В сетевой микросервисной среде у вас априори более слабые возможности по контролю прохождения вызовов.
Если вы это не учитывайте — запросто можете получить плохо работающую систему.
Если вы это учитывайте — то пишите больше кода.
Tiendil
01.11.2018 11:55-1Код инициалиазции, переподключения, обработки ошибок содинения пишется один раз.
Далее идеёт код логики: ветка если всё хорошо, ветка если операция провалилась (условно). Ветка для обработки ошибок писалась бы и в случае монолита.
Для примера: в монолите пишется код для обработки ошибок при работе с базой, в микросервисной архитектуре — для ошибок при работе с сервисами. Частота ошибок может быть разная, но код писать всё равно надо и во многих случаях он выглядеть будет одинаково.
andreyverbin
01.11.2018 12:58если логика задачи требует повторных попыток?
То они были бы и без микросервиса.
Не были бы. В монолите была бы вызвана функция и все. В микроскопическое надо учитывать, что ваш сервис может рестартовать. В каждом случае прийдется решать отдельно как делать повторные вызовы: сколько ждать, сколько раз повторять, нужно ли вообще что-то делать если это ошибка DNS и т.п.
0xd34df00d
31.10.2018 20:20Но я больше не могу рассуждать об этом коде так, как я бы рассуждал о нём в случае выполнения в рамках одного процесса.
Прячет ли RPC-прослойка от меня, например, возможность неудачи?
1. Если да, и она повторяет вызов ещё (и ещё, и ещё, и ещё...), то, во-первых, я не уверен, что это оправданная стратегия, во-вторых, я больше не могу прогнозировать время выполнения таких вызовов вообще никак.
2. Если нет, то всё совсем очевидно.Tiendil
01.11.2018 10:02Для сложно проекта это о-маленькое от необходимых решений при анализе кода. Эти вопросы и так везде стоят. Есть же базы, кэши, отложенные задачи, внешние сервисы какие-то. В случае работы с ними, те же самые вопросы встают при каждом обращении.
Для большинства случаев достаточно выработать соглашение в проекте по стандартному поведению в случае ошибок и закрепить его в коде. Это делается 1 раз.
Для особых случаев всегда приходится применять особые меры и решения, безотносительно того есть там обращение к микросервисам или нет его.
И само собой, микросервис — не серебрянная пуля. Если он реально мешает в каком-то частном случае, то не надо этот микросервис выделять.
VolCh
31.10.2018 23:43Тогда это перераспределение типов задач одних и тех же людей. Ну если вы не какой-то гигант где для каждого действия специально обученный человек, типа один бинарники заливает, другой их запускает.
Ogoun
31.10.2018 14:32Стоит рассматривать исходя из задач проекта. Где-то логичнее монолит, где то микросервисы, а чаще всего гибридные решения будут лучше всего.
В текущем проекте, работа системы должны идти 24x7, и микросервисы позволяют мне производить обновления на горячую (запустил новую версию параллельно старой, новая версия включается в балансировку, старая останавливается и удаляется), с монолитом такой сценарий намного сложнее.
Балансировку нагрузки в монолите можно реализовать по сути только на уровне всего сервиса, поднять рядом такой же сервис и чем-нибудь разруливать входящие запросы (NLB, ngnix и т.п.). Микросервисы же позволяют делать все намного гибче, если анализ показывает что узким местом является конкретный сервис, достаточно просто запустить его копию, по рессурсам намного менее затратно.
На прошлом проекте был проект бэкофиса, с небольшой нагрузкой, и с временем простоя ночами, когда не было пользователей, монолит подходил идеально.
В общем мысль такая, что архитектуру всегда нужно выбирать исходя из текущей задачи, а не из трендов в статьях.stratosmi
31.10.2018 18:36+1микросервисы позволяют мне производить обновления на горячую (запустил новую версию параллельно старой, новая версия включается в балансировку, старая останавливается и удаляется)
Blue-green deployment это называется.
С монолитами вы тоже можете это делать. Точно так же.
SUA
31.10.2018 15:04Микросервисы это хорошо… когда они «микро» и реально изолированы друг от друга
когда же методу требуется5 перекрестных вызовов между микросервисами, чтобы собрать все данные.
— это верный признак что что-то пошло не так
… а так и кусок вполне ощутимого по размерам монолита вполне может являться микросервисом для других приложений — по сути это все публичные API крупных интернет-компаний (метрики, картография итп), с тем лишь исключением что их работа — не совсем собственная забота
alatushkin
31.10.2018 17:55+2Из тех проектов, что я видел, часто с помощью «микросервисности» пытаются решить проблемы «монолита», которые обычно возникают от недостатка «дисциплины» и/или «осознанности» в разработке архитектуры.
Главное в этом деле — сменить работу раньше чем компания столкнется с последствием твоего решения. Тогда можно будет на митапах бодро рассказывать как внедрил микросервисную архитектуру, пока ищешь новую жертву.
bo0rsh201
31.10.2018 19:50Два чая этому господину. Вот так взяли и структурированно и понятно описали именно то, что мне каждый раз приходит в голову, когда слышу очередные истории успеха от адептов микросервисов. Единственный вменяемый аргумент это возможность проще скейлится и делать это динамически + нет привязки к одному стеку company wide. Но это плюсы, которые действительно полезны на большом масштабе, а не в проекте уровня CRM система на заводе
stratosmi
31.10.2018 20:14Единственный вменяемый аргумент это возможность проще скейлится и делать это динамически + нет привязки к одному стеку company wide.
Масштабироваться можно и монолитами. Не столь идеально попадать в аппаратные ресурсы, конечно. Но горизонтальное масштабирование все так же делается и монолитами.
Стек — не столь большая проблема. Если уж вы принципиально считаете, что вот этот кусок кода лучше переписать на чем то другом — ну отделите его в отдельный сервис (пусть не микро).Archon
31.10.2018 23:06Микросервисы имеют смысл тогда, когда «не столь идеальное попадание в аппаратные ресурсы» обойдётся дороже, чем затраты компании на микросервисы. Не знаю, сколько в нашей стране компаний с нагрузкой такого масштаба, но подозреваю, что в пределах сотни, если не дюжины. А микросервисы, меж тем, пытаются пихать в каждый второй стартап.
funca
31.10.2018 22:04Как делаешь, так и получается. Микросервисная архитектура это про то как иначе поделить большую работу между маленькими командами. Классический просчет при переходе от монолитной архитектуры к микросервисам — оставить процессы разработки и принципы владения кодом без изменения. Тогда к текущим затратам добавится расходы на девопс, интеграцию, тестирование, мониторинги, документацию и много другого подобного затратного счастья. Если бизнесовые потребности требуют менять over9k микросервисов ради одной фичи, что то не так в вашем подходе.
Antigluk
31.10.2018 22:08Самая большая боль, как по мне, так это развертывание всей этой карусели на локальной тачке. Допустим, часть сервисов крутится на стейджинге, а для разработки нужно поднять только часть из них: и начинается переписывание конфигов каждого из сервисов, чтоб они смотрели друг на друга.
Это занимает много времени и порождает желание написать свои костыли в виде каких-то генераторов конфигов.
Вот как вы живете с этим? Может есть таблетка от этого?biseptol
01.11.2018 00:11Если они очень часто смотрят друг на друга — возможно, в архитектуре надо что-то исправить.
creker
01.11.2018 00:47Разве minikube не для этого придуман? А ежели сервисы настолько переплетены, что для разработки нужно поднять почти их все, то наверное действительно надо в архитектуре что-то исправить.
stratosmi
01.11.2018 09:10А ежели сервисы настолько переплетены, что для разработки нужно поднять почти их все, то наверное действительно надо в архитектуре что-то исправить.
В логике бизнес-задачи это может быть изначальным.
Если основная цель вашего проекта — оказание одной-единственной основной услуги и вы проводите проверку функционала этой самой основной услуги, например.
Тогда все большая часть модулей вашего проекта направлены именно на это.
Ибо зачем вы остальные-то модуля писали вообще, если без них можно обойтись?
Пример интернет-магазина habr.com/company/raiffeisenbank/blog/427953/#comment_19310299
Не так уж много частей не задействовано, если мы проверяем ключевую операцию для такого проекта — как протекает оформление товара в целом.
VolCh
01.11.2018 09:35Миникуб или локальный докер (сварм) придуманы для этого, но в сложных проектах их недостаточно, банально не хватает ресурсов даже на мощной дев-машине поднимать десятки сервисов у каждой из которых своя СУБД. Не БД, а СУБД — отдельный мастер-процесс.
Kirhgoff
01.11.2018 01:02У нас коллега запилил специальный докер контейнер, который запускаешь на локальной тачке и там вся инфраструктура со своими взаимосвзями живет (но только по одному сервису). Единственное, надо базу сидить после обновлений или миграций.
VolCh
01.11.2018 09:38Когда нужен только один сервис локально, а остальные со стейджинга идут, то нормально разруливается с локальным .env файлом в корне сервиса для докера. Или сервисов немного или они легкие, то и просто запустить всё локально приемлемо.
funca
31.10.2018 22:15+1В айти есть всего несколько количественных категорий: ноль, один, много и дофига. При переходах их одной в другую требуются принципиальные изменения. Нельзя просто так взять и распилить монолит на несколько кусков с кучей связей и назвать их микросервисам. Осколочная архитектура думаю будет более подходящим названием.
unbelieving
01.11.2018 04:18Тут все забыли еще один существенный момент — кучка микросервисов сожрет вычислительных ресурсов заметно больше, чем монолит. Хотя бы на том, что при передаче запросов между микросервисами данные надо будет перевести из внутреннего бинарного представления во внешнее (xml/json/...), затем преобразовать их назад в бинарное, по дороге проверив корректность данных, права доступа и т.п. В монолите все это делается один раз, в микросервисе десятки, а то и сотни раз за цикл обработки одного запроса.
stratosmi
01.11.2018 09:13В монолите все это делается один раз, в микросервисе десятки, а то и сотни раз за цикл обработки одного запроса.
Ничего страшного.
Компьютеры давным-давно уже настолько шустры, что эти вещи мало кого волнуют.
Бизнес согласен платить больше за железо — лишь бы выйти на рынок раньше, лишь бы получить хоть как-то работающую систему, лишь бы иметь возможность подстраиваться под рынок оперативнее.
Чем получить систему более эффективно использующую железо, но позже.
unbelieving
01.11.2018 10:04Да, да. Именно это и говорили руководители компании, где я раньше работал. А потом один из крупнейших заказчиков сказал, что ожидал производительности, на выделенном под проект железе, раз в 100 выше, чем получилось на микросервисах. И для продолжения разговора надо поднять ее хотя бы в 10 раз. Поднять всем понятно как — частично смонолитить.
Итог — той компании нынче не существует. А жаль и идеи хорошие были и коллектив сильный. А бездумный микросервисный подход живее всех живых и утопит еще не одну компанию.
Я не против микросервисов, и красиво и местами действительно годно. Но это не серебряная пуля на все случаи.stratosmi
01.11.2018 11:27-1Итог — той компании нынче не существует. А жаль и идеи хорошие были и коллектив сильный
Если компании по итогу не существует именно из-за технической ошибки, то коллектив там был сильный?
VolCh
01.11.2018 09:51Это предсказуемые, даже очевидные минусы.
unbelieving
01.11.2018 10:17Видимо на столько очевидные, что ни в одной презентации от лидеров рынка про это ни слова. Ни в одной концепции развития у крупных заказчиков не видел. Обратное утверждение, про снижение числа вычислительных ресурсов иногда встречал.
У всех виденных мной расчет экономики строился как минимум на не увеличении серверного парка, тепла, места, числа сетевых интерфейсов…
Тут есть всего два варианта — либо уважаемые эксперты не в курсе очевидного минуса, либо они наглые обманщики. Выбор варианта по вкусу.VolCh
01.11.2018 11:41Википедия:
Архитектура постоянно подвергается критике с самого момента её формирования, среди новых проблем, которые возникают при её внедрении отмечаются:
сетевые задержки[5]: если в модулях, выполняющих несколько функций, взаимодействие локально, то микросервисная архитектура накладывает требование атомизации модулей и взаимодействия их по сети;В целом же по меркам ресурсов микросервисы могут приводить к их экономии, если минусы издержек с лихвой компенсируются плюсами от раздельного масштабирования.
Грубо, если монолит из M модулей, работающий в N инстансов (в целях производительности), вы разобьёте на M микросервисов в тех же N инстансах каждых, то вы практически гарантированно получите большее потребление ресурсов. Но если при разбиении монолита только несколько модулей запустите в N инстансах, а остальные в 1, то вполне можете покрыть издержки на микросервисную архитектуру без потери общей производительности, но, возможно, со значительной общей экономией ресурсов.
vanxant
Микросервисы — это естественная реакция разработчиков «средних» компаний на изменившиеся условия. Писать всё своё с нуля могут только крупнейшие игроки (Apple/Google/Microsoft), но и там это считается антипаттерном NIH. А все остальные вынуждены юзать тонны чужого кода от разных вендоров.
С другой стороны, появление этих ваших гитхабов и гибких методологий привело к rolling release-ам, точнее к отсутствию релизов как таковых. Есть поток отладочных версий библиотек с кучей багов, которые никто не собирается фиксить, а вместо этого просто выкатывают новую, несовместимую со старой версию со своими свежими багами.
Вы начинаете более-менее крупный проект, берёте свежайшие либы и, пока дойдёте до версии 1.0, выясняете, что ваши либы устарели уже на пару мажорных номеров. С монолитом просто так взять и обновиться нельзя, нужно переписывать кучу кода и заново его тестировать.
Микросервисы решают этот вопрос тем, что позволяют себя переписать на новой либе или вообще новом языке за те пару месяцев, пока версии ключевых либ считаются «свежими».
Плата за это — да, налог на девопсов, а также сложноуловимые баги «между» микросервисами, когда непонятно, кому вообще заниматься отладкой.
G1yyK Автор
> С монолитом просто так взять и обновиться нельзя, нужно переписывать кучу кода и заново его тестировать.
С микросервисами тоже просто так обновится нельзя, переписали сервиси — надо так же все тестировать, где гарантия что сервис переписан коректно.
> Микросервисы решают этот вопрос тем, что позволяют себя переписать на новой либе или вообще новом языке за те пару месяцев, пока версии ключевых либ считаются «свежими».
Пока переписываем микросервис — либы опять устаревают? тут наверное нужно гнатся не за либами — а найти компромис между «старыми» либами и работающим функционалом.
kaljan
небольшой сервис тестить всяко легче монолита
G1yyK Автор
Надо будет прогонять бизнес тестирование что для монолита, что для маленького сервиса — по трудозатратам выходит одинаково. А функционально проверить изменения и в монолите можно если это не спагетти код.
Плюс спорный вопрос, что тестить проще. Если монолит целиком переписать и потом его тестировать — то ну его нафиг, так вообще не полетит. А если сделать roadmap для переезда на новую платформу(ради чего мы переписываем), то изменения можно будет да же под бизнесовыми задачам провести и протестировать.
guility
Боюсь, без измерений все заявления, что «будет быстрее» или «будет затрачиваться столько же времени» — беспочвенны, пока мы не проведём конкретный эмпирический тест, чистота которого, так или иначе, будет весьма сомнительна.
Однако, в целом, вы пишите фактически только про изолированность, документированность и чистоту кода.
Однако, микросервисы — это уход, в первую очередь, от инфраструктурных проблем.
Потому что монолит — требует, чтобы одна единственная машина могла предоставить все необходимые пакеты(модули) и все необходимые ресурсы требуемые для решения задачи одновременно.
Когда речь идёт о каком-нибудь многоуровневом стэке технологий(когда одни библиотеки опираются на кодовую базу других) — все хорошо.
А вот как только вы используете разноплановые библиотеки из разных технологических стеков — запуск и развертывание монолитного решения становится задачей почти фантастической, т.к. постоянно вылезают противоречивые требования или прямые несовместимости библиотек.
А вот когда дело доходит до обработки больших данных… ух. Тут микросервисы, каждый из которых должен анализировать свой кусок данных на недорогих инстансах 4+4(4 vCPU+4GB RAM), или давать быстрый ответ для пользователей в своей географической зоне — незаменимы.
К тому же, в тех же направлениях распределенных вычислений фрагментация пакетов-модулей — гораздо выше, чем в «традиционных» областях, что создаст огромное количество проблем при попытке обновления каких-то библиотек в монолите.
Так что — все зависит от поставленной задачи, которая диктует выбор технологического стэка(или россыпи).
Если ваша задача решается стэндалон, или единичным сервером на «стратифицированном» технологическом стэке — вполне вероятно, что монолит — будет хорошим решением.
Если же нужна распределенная система, или большое количество несвязных модулей/библиотек — добро пожаловать в микросервисную архитектуру.
Ну и CI/CD, как правило, все-таки гораздо легче, как минимум по машинным ресурсам — решается на микросервисах.
sentyaev
С микросервисами сложность инфраструктуры как раз растет.
VolCh
Инфраструктура инфраструктуре рознь. С микросервисами растёт сложность инфраструктуры оркестрации, диспетчерезации и т. п., но падает сложность инфраструктуры локальной среды исполнения. Например, в микросервисах нет необходимости синхронизировать версии одной библиотеки, используемых в разных модулях, а в монолите может оказаться не обойтись без переписывания кода.
Bonart
Инфраструктура для набора микросервисов, решающих те же задачи, что и монолит — сложнее по построению.
Переход на микросервисы сам по себе ничего не упрощает, но превращает часть внутрипроцессных вызовов в медленные, ненадежные, плохо контролируемые на соответствие соглашениям сетевые.
И все это ради единственного преимущества: селективного горизонтального масштабирования.
VolCh
Навскидку ещё два: селективный деплой и (в теории) возможность работы в режиме частичного отказа.
Bonart
В частичный отказ монолит «умеет» и самостоятельно.
Селективный деплой для монолита сложнее, но также возможен при аналогичном подходе к проблемам совместимости.
Virviil
Я всегда думал, что "частичный отказ" подразумевает поломку сервиса, сопровождающейся простоем.
Если сервис "один из..", в микросервисной архитектуре — получаем как раз "частичный отказ". Если сервис "всего один", как монолит — то либо работает либо нет. Как может "частично" работать (а вернее "частично не работать") монолит в данном контексте — не понятно.
stratosmi
может же быть несколько экземпляров.
ну например, повреждена БД.
операции с ней невозможны.
но все что не требует СУБД — успешно работает.
VolCh
Про СУБД уже не совсем монолит. Отказоустойчивое масштабирование тоже не про частичный отказ. А так: ошибка при запуске процесса, какой-нить сегфолт. Все дцать инстансов сегфолтятся. Если такое случится с каким-то неключевым микросервисом, то приложение будет работать пускай и не полностью.
stratosmi
С этим не все так просто.
Возьмем конкретный ясный всем пример — интернет-магазин.
Не работает хоть что-то из этого: корзина, каталог товаров, оформление товаров, прием оплаты-онлайн. У вас нет интернет магазина.
То, что работает при этом уведомление пользователей по СМС, уведомление пользователей по e-mail, полнотекстовый поиск, статьи блога, система рекомендаций товара, веб-сайт в целом — ситуацию не изменяет. Все равно у вас нет интернет-магазина.
linux_art
Очень хороший пример. Правда не совсем полный. То что работает веб-сайт в целом изменяет ситуацию с точки зрения падения в поисковой выдаче. Магазин может не продавать и падать в выдаче. А может не продавать и оставаться в выдаче на том же месте, если лежит частично, а не полность.
VolCh
Слово «неключевым» заметили?
Да даже с инет магазином: не работает приём оплаты: люди могут продолжать просматривать товары, набирать их и т. п. Пока они это делают, приём могут уже починить. Не работает корзина: могут хотя бы просматривать, выбирать (в смысле сравнивать разные товары и подходить к принятию решения). Не работает каталог: могут оформлять оплату те, кто успел набрать корзину до отказа. Ну и по идее при отказе микросервиса будет выводиться не обычная 500-я, а внятное сообщение о временной неработоспособности конкретной функции.
А вот если монолит падает, то в лучшем случае какая-то 500-я будет и работать не будет ничего. Естественно я о фатальных отказах, приводящих к сегфолтам, а то и паникам, в лучшем случае к выходу из процесса с ошибкой, а не о логических на уровне модулей.
stratosmi
Формально — да, как бы работает.
Но от простого просмотра каталога до реального заказа доходит хорошо если 1 из 1000.
Так что падение каталога — это фатально.
Да и привел пример, когда «неключевых» мало.
Их всегда мало, если сервис специализируется на одной услуге.
VolCh
Не так фатально как для монолита. Хотя бы с саппортом можно початиться, получит эстимейты нормализации работы
mayorovp
Селективный деплой (не путать с горячей заменой модулей!) без проблем делается и в монолите, если заранее заложить его в архитектуру. Пишу как разработчик как раз такой архитектуры в нескольких проектах. Ничего сложного тут нет, надо лишь выделить ядро, и продумать интерфейсы для взаимодействия модулей — то же самое, что пришлось бы делать и в микросервисах, но чуть проще. При старте сканируется папка bin, из нее загружаются все библиотеки и скармливаются IoC-контейнеру.
RPG18
Прежде чем рефакторить, нужно написать тесты или нет? Или в райффайзенбанк не пишут юнит, функциональные, интеграционные, автоматические тесты?
andreyverbin
С чего бы это? Когда тестим монолит тестим сразу все, а если протестировали сервис, то нет гарантий, что он нормально интегрирован с окружением. Тестировать сервис сложнее, хоты бы потому, что окружение сложнее.
kaljan
Изменение в монолите может аффектнуть кусок в другом конце системы, а для большого легаси проекта это очень больно, таким образом, после рефакторинга и выделения сервиса (естественно с покрытием тестами) работать с микросервисом будет легче. Не все микросервисы имеют миллиард связей с соседними системами
bo0rsh201
Так. Стоп. То есть юнит тесты на пакет/класс в коде вас не устраивают, а вот если вынести это в отдельное приложение и сделать такие же тесты, то все магически меняется?
Великолепная логика
kaljan
я не до конца понял, как Вы к этому выводу пришли
VolCh
Скорее речь о тестах, требующих запуск полноценного процесса в полноценном окружении, с разворачиванием хранилищ и моков внешних сервисов типа платежных систем.
VolCh
Тестировать сервис проще. Тестировать систему сложнее.
Bonart
Даже сервис тестировать сложнее, чем модуль внутри монолита, решающий те же задачи.
VolCh
Вот не факт. Пример: для теста нужна БД, для монолита вам надо создать 500 табличек, для сервиса пускай 10.
Bonart
Для теста модуля монолита БД может быть не нужна совсем. Или нужна, но те же 10 табличек. Сервису же для тестов в любом случае надо базу и сетевого клиента.
Если для тестов модуля монолита нужны все 500 таблиц, то он плохо спроектирован. Такой же по качеству микросервис также захочет 500 таблиц из базы, которую будет делить еще с 50 микросервисами.
nApoBo3
Для теста ни база, ни сетевой клиент не нужен.
Микросервис байдизайн должен иметь выделенную базу, ну или не иметь базы совсем.
VolCh
Монолит просто стартовать не должен в общем случае при 10 табличках в базе, если он ждёт 500. Или должен но производить разворачивание базы. Ну просто нет базы начинает накатывать миграции. Или для каждого теста писать свои миграции?
Free_ze
По логике, микросервис не должен лезть в чужие базы. Миграции у него должны быть свои, согласованные с версией этого микросервиса.
VolCh
Я про тестирование монолита из 50 модулей по 10 таблиц на каждый (часто с foreign key между модулями, но замнём). Как в такой ситуации его тестировать? Общий поток миграций накатывать? Привязывать миграции к модулям? Ручками или костылями привязывать к тесту собственные миграции, синхронизируя с обычными? Копировать часть схему из эталонной базы?
Bonart
Ничего, что речь шла о тестирование модуля монолита, умеющего то же, что и один микросервис?
Если каждый модуль нуждается в той же базе, что и монолит в целом, проблема не монолитности, а в качестве проектирования.
VolCh
Каждый модуль нуждается в своих 10 табличках, но для тестирования модуля нужно запустить монолит, который нуждается в в 500 табличках всех модулей, ведь он монолит — или всё или ничего.
Bonart
Я не знаю, зачем вам для тестирования одного конкретного модуля надо запускать монолит целиком.
Модульность затем и нужна, чтобы разрабатывать и тестировать модули можно было независимо.
VolCh
Это суть монолита, он по частям не запускается. Вот есть один бинарник и запустить мы его можем только целиком.
Free_ze
Ох, извиняюсь, прочел то, что хотел видеть, подразумевая микросервисы.
Однако, никто ведь не мешает так категорично поделить и модули монолита, т.е. каждый модуль — со своими базами. Настроить деплой — это задача не сложнее аналогичной для микросервисов.
И его так же можно делать тестирование, без остальных модулей («монолита»).
VolCh
Это будет уже не совсем монолит, ведь таким путём можно дойти и до одного бинарника вроде монолитного, но список модулей (в пределе только из одного) берущего из конфига, а если в ходе работы вызывается какой-то не подключенный модуль, то ищущий среди своих инстансов тот, где он подключен, и дергающий его по сети. Это ещё будет монолитом? )
Free_ze
Использование IoC-контейнеров (которые позволяют динамическую конфигурацию) — это довольно распространенная практика для монолитов. Системы плагинов и динамически загружаемые библиотеки — тоже не новый революционный подход. Это требование SRP.
Если есть сетевое взаимодействие между инстансами, это уже не монолит.
Зачем дергать по сети то, что можно загрузить в память и вызвать напрямую? Интерфейс известен заранее.
В контексте сравнения с микросервисами, которые представляют собой разные процессы, единая программа, скомпонованная из модулей вне рантайма больше похожа на монолит. Монолит в этом случае вполне может состоять из разных исполняемых модулей (физически разные файлы), это не играет роли.
VolCh
А если нельзя загрузить в память? Памяти уже нету, а на соседнем инстансе есть.
Вообще спор монолит вс микросервисы больше просто обсуждение где остановиться в декомпозиции, а не плюсы или минусы декомпозиции в целом поскольку настоящих монолитов, не обращающихся по сети или локальным сокетам к сторонним процессам, очень мало осталось, по-моему. N-звенная архитектура, выделенная СУБД — уже не монолит, запускаемая по расписанию в отдельном процессе задача пускай того же бинарника — тоже.
Вот я более чем уверен, что подавляющее большинство в этом топике говоря о монолите, например, в вебе, имеют в виду что-то вроде: клиент в браузере, веб-сервер, апп-сервер, СУБД, какой-нибудь редис, скорее всего где-то крон в фоне, может даже очередь с воркерами отдельными. Отдельная система анализа логов и мониторинга, автоматического перезапуска при краше. И про всё это говорят «у нас монолит». При это ещё прикладывая усилия для того, чтобы части апп-сервера минимально зависели друг от друга, обновлялись на лету, не загружались пока не нужны и выгружались когда уже не нужны.
Когда-то почти перестали писать реально монолитные приложения, выделяя из них сервисы, а часто не выделяя, а удаляя из них «наколенке» реализованную функциональность и вместо неё подключая сторонний сервер типа веб-сервера или СУБД — а это уже сервисно-ориентированная архитектура. Микросервисная — лишь дальнейшее разбитие, начавшееся в тот момент, скорее всего, когда кто-то решил «а давайте СУБД у нас будет отдельным сервисом» или «а давайте UI вынесем в отдельный сервис». После этого уже не стало монолитов а спор монолит вс микросервисы превращается в спор о том, нужно ли один большой самописный сервис («монолитный» апп-сервер, бесполезный без кучи других сервисов) дальше разбивать на более мелкие сервисы или пора остановится.
mayorovp
Не совсем так. Это не мы говорим "у нас монолит", это приходит фанатик микросервисов и говорит "у вас не микросервисная архитектура? Значит, у вас ужасный монолит!"
VolCh
Ну это фанатик. ) Но дискуссии именно о монолите, то есть «вы» принимаете его точку зрения и доказываете, что ваш монолит не так уж ужасен, и масштабироваться может, и по частям деплоиться и т. д.
MikailBag
Берем и суем вместо обычного клиента БД собственный, возвращающий тестовые данные. В чем проблема?
VolCh
это уже будет не тестирование монолита, а только какой-то его части.
MikailBag
По-моему, модульное тестирование всегда делают с подмененной БД, а e2e с настоящей. Ну а БД вообще не часть приложения.
VolCh
Про модульное речи нет, там вообще без разницы если одни и те же принципы использованы. И не всегда без БД.
MikailBag
Значит вы про е2е тесты.
Там по-любому потребуется полная БД и все микросервисы/монолит. И опять с микросервисами сложнее.
VolCh
Скорее про тесты конкретного HTTP API ендпоинта. В реальности подавляющее большинство запросов на него идёт из браузерного фронтенд-кода, но для этих тестов достаточно любого тестового http-клиента. То есть не полное тестирование системы, а только части серверного API.
Bonart
Реализация конкретного API микросервиса может делать вызовы к другим микросервисам и для полноценного тестирования извольте поднимать весь оркестр.
А у модуля никакого WebAPI и тем более базы может вообще не быть. Достаточно обычных ООП-интерфейсов. У монолита WebAPI будут трогать только E2E-тесты.
VolCh
Поднимать или мокать — отдельный разговор.
У модуля может быть любой API в том числе WebAPI, и база своя, ну или свои таблички в общей базе. Вот модуль аутенфикации и авторизации. Ему нужен свой ендпоинт, чтобы браузер или иной клиент стукнулся, ему нужна база, чтобы хранить юзеров, пароли, роли, права и связь этого всего друг с другом. Как вы будете тестировать авторизацию без WebAPI и базы? Как проверите, что, например, роутинг корректно настроен и объекты на базу корректно смаплены? и вообще всё это друг с другом связано. Это ещё не e2e с точки зрения всей истемы, потому что UI не задействован, но это тест WebAPI. Грубо, после его прохождения бэкендера можно на другой модуль или проект переводить, а не ждать пока фронтендеры что-то сделают.
Bonart
Двумя сообщениями выше:
Не надо сравнивать тестирование монолита целиком и одного микросервиса.
Один микросервис есть смысл сравнивать с одним из модулей монолита.
VolCh
Имеется в виду что тестирование сервиса от API ендпоинта до базы включительно не будет эквивалентно тестированию монолита от того же апиендпоинта но без базы. Слой клиента базы тестироваться не будет, если мы его подменим, база тестироваться не будет. Протестируем как модуль интегрируется с базой в лучшем случае, но не проверим как он работает с базой.
Bonart
В том-то вся и штука, что микросервис надо тестировать с клиентом и базой, у модуля же клиентом будет тестовый фреймворк, а с базой напрямую ему работать без надобности.
VolCh
Вот как модулю авторизации не работать с базой юзеров? Ещё раз, мы обсуждаем эквивалентное тестирование микросервиса по сравнению с эквивалентным модулем монолита. Это значит, что если у микросервиса есть ендпоинт и база, значит и у модуля есть. Если на тесте микросервиса мы проверяем весь флоу от отработки сетевого запроса от клиента до работы с базой, значит и для модуля мы проверяем то же. Мокаете работу с базой при тестировании модуля авторизации — мокайте её и при тестировании микросервиса. Не делаете реальный http-запрос при тестировании модуля, а стучитесь к роутингу как-то напрямую — не делайте его и при тестировании микросервиса, только в нём роутинга можте не быть вообще :)
stratosmi
Ну вы так же можете тестировать монолит всего лишь юнит-тестами.
Нет? Хотите интеграционные?
А почему с микросервисами не считаете нужным интеграционные?
Потому что это гораздо сложнее?
Мартин Фаулер хорошо разжевал что не все так просто
habr.com/post/261689
И ребята из Фланта
habr.com/company/flant/blog/427283
За все приходится платить.
В том числе и за видимую «простоту деплоя одного сервиса».
Серебряной пули так все еще и нет.
Где-то что-то имеет какие-то плюсы. Но имеет и минусы.
kaljan
я клоню к тому, что в случае с микросервисами тестов меньше, и нагрузка на их содержание меньше, но нагрузка на инфраструктуру растет
RPG18
Нет. От того что функционал вынесен в отдельный сервис, не уменьшает количество тестов на этот функционал. При этом уже нужно писать интеграционные тесты.
kaljan
1. Количество тестов у монолита > количества тестов у сервиса, который из монолита выдернули
2. Если при выдергивании сервиса из монолита сложность только возросла и появилось n^2 интеграций — это корявое выдергивание, надо брать больший кусок
RPG18
А теперь возьмите сумму тестов всех микросервисов и сравните с количеством тестов монолита. Тесты пишутся на функционал, функционала при микросервисной архитектуры меньше не становится.
stratosmi
Вы упускаете более высокую сложность интеграционных тестов для микросервисов.
Когда что-то в полноценном тесте всей системы пошло не так — разобраться, что виноват не ваш измененный микросервис, а косяк где-то в том (который вы вроде и не меняли), что вызывает тот, который вызывается тем, что вызывается из вашего — не проще.
Да, да, да. Это так же сложно выглядит при отладке как и сложно выглядит мое описание проблемы.
kaljan
логи спасут мир
RPG18
Что-то не спасают. Поэтому появились сервисы для трассировки.
stratosmi
Конечно, конечно.
При этом, чтобы понять что там происходит, вам нужно совместить логи с разных микросервисов, чтобы было понятно, что они относятся к одному и тому же запросу.
И хорошо, если речь идет только об «линейно проходящих» запросах.
А если это фоновые процессы, запускаемые при разных условиях? Или если это несколько параллельно порожденных вызовов внутри микросервисной системы?
А если вам не хватит информации в логах? Добавить, сделав логи более подробными — не проблема. Но вам придется изменить и перезапустить некий третий микросервис только для того, чтобы отладить первый.
Никто не говорит, что в микросервисах невозможно отлаживать в принципе.
Просто микросервисы выглядят как бы простыми в отдельности, если забыть о том, что нам-то (бизнесу, заказчику) нужна работающая вся система в целом.
Когда вы переходите на микросервисы — сложность никуда не уходит.
Просто из монолита сложность размазывается между микросерисами и связями между ними.
Был большой комок грязи в монолите.
А стал большой комок грязи в связях между компонентами.
У микросервисов есть свои преимущества. Которые являются недостатками в монолитах.
Но микросервисы вовсе не универсальная серебряная пуля. Так как появляются и новые недостатки. Которые в монолитах не так остры.
Серебряной пули, волшебной «лучше всех» технологии не существует в сравнении монолиты vs микросервисы. Нужно смотреть по конкретной задаче.
bo0rsh201
Вместо find usages и проверки всех использований вам надо каким-то образом при любом изменении бегать по графу зависимостей всех ваших сервисов, причём рекурсивно.
Bonart
Ага, особенно хорошо тестировать End2End
stardust_kid