Сегодня особую популярность получила микросервисная архитектура веб-приложений. У такого подхода есть много известных сторонников. К ним относятся Facebook, Uber, Groupon, Klarna, Amazon, Netflix, eBay, Comcast и другие. Но насколько необходим подобный подход в каждом конкретном случае?
Когда нужны микросервисы?
У микросервисов есть ряд предполагаемых преимуществ. Почему предполагаемых? Дело в том, что их можно получить не только с помощью микросервисов. А большую часть, если даже не все преимущества, можно получить и с помощью монолита.
Микросервисная модель действительно делает приложение более гибким, позволяет перейти на другой уровень решения имеющихся проблем.
Но за все приходится платить, и за микросервисы тоже. Они, как известно, очень дорого обходятся в создании и при обслуживании.
Если вам нужна эта дополнительная гибкость? Прекрасно. Тогда на микросервисы стоит обратить внимание. Возможно, дополнительные затраты в конечном итоге окупятся.
А если нет? Вы серьезно перегрузите стек используемых технологий, что может затруднить для клиента взаимодействие с приложением.
Рассмотрим основные преимущества микросервисов и подумаем, как можно добиться подобных с помощью монолита.
Масштабируемость
Каждая функция микросервисного приложения выполняется на собственных ресурсах, которые могут масштабироваться независимо друг от друга. Конечно, это позволяет эффективно контролировать предоставляемые функциям ресурсы.
Но насколько необходим подобный уровень контроля? Какую загруженность испытывают разные функции приложения? Свойственно ли им индивидуальное масштабирование? Какие у каждой функции требования к ЦП, памяти, хранилищу и графическому процессору?
Добавляем ресурсы, устраняем проблемы монолита
Для многих команд проблему недостатка ресурсов во многих ситуациях проще решить за счет масштабирования аппаратных средств. Т. е. в большинстве случаев детальная оптимизация работающей инфраструктуры ПО экономически нецелесообразна.
Проблемы с производительностью и функционированием в монолите, скорее всего, легче устранить, чем переходить на новый шаблон архитектуры. Конкретное решение зависит от стека используемых технологий, но не потребует особых усилий.
Распределите трафик на независимо масштабируемые кластеры
Если у вас несколько серверов, размещайте перед ними какой-нибудь балансировщик нагрузки. Можно конфигурировать этот балансировщик для маршрутизации трафика в независимо масштабируемые кластеры экземпляра вашего приложения.
Также с помощью независимо масштабируемых очередей можно переносить асинхронные задачи в фоновые задания. Убедитесь, что у вас достаточно очередей для сокращения затрат на инфраструктуру.
Изоляция отказов
Серьезным преимуществом правильно спроектированной архитектуры микросервисов является отсутствие влияния при сбое одной из функций на остальные.
Маршрутизация трафика в изолированные кластеры
Обеспечить определенную степень защиты от сбоев также может идея маршрутизации различных видов трафика в кластеры масштабирования.
Проанализируйте причины прошлых ошибок. Это позволит наилучшим образом распределить трафик. Если есть нестабильная второстепенная функция, которая часто вызывает общий сбой, возможно, стоит направить ее конечную точку в собственный кластер экземпляров приложения. Если есть проблемные фоновые задания, поместите их в их собственную очередь, которая не влияет на другие задания.
Автоматизированное тестирование
Профилактика лучше, чем лечение. Если можно предотвратить или хотя бы сократить ошибки и сбои, тогда придется гораздо меньше беспокоиться об их изоляции.
Формирование навыков тестирования является ключевым фактором уверенности в качестве программного продукта, в его способности надежно обеспечивать требуемую функциональность даже при рабочей нагрузке.
Язык программирования и технологический агностицизм
Не стоит использовать дополнительные языки и технологии вне рамок отдельных сервисов. Как правило, излишняя свобода в выборе языков и технологий может привести к фрагментации и чрезмерно сложному технологическому стеку.
Оцените наглядность и упорядоченность монолита.
Если по специфическим доменным требованиям для конкретных функций нужны специализированные языки, можно рассмотреть возможность использования отдельных сервисов. Следует сравнительно оценить выгоду, которую приносит любая дополнительная технология, с сопутствующими ей затратами на обслуживание.
Безопасность данных
Есть мнение, что защитить монолит сложно, но микросервисы только усложняют эту задачу. Увеличивая сложность стека, вы расширяете зону атаки.
Понятно, что выделение функций в разные сервисы позволяет применять разные уровни безопасности и активности к каждой из них. Однако подумайте, насколько необходим такой уровень контроля.
Не проще ли будет обезопасить весь монолит на самом высоком по необходимости уровне? А есть ли у вас вообще разные требования к безопасности данных?
Автономность команд
Я сторонник автономных групп разработчиков разного профиля. Но не совсем понимаю, откуда для этого появилась идея введения сетевого разграничения.
Предоставление каждой команде в монопольное пользование определенных автономных (изолированных) систем может показаться способом повышения автономии, но на самом деле это может сработать и против нее.
Представим, что одной команде нужно частично изменить функциональность, которой владеет другая команда. В архитектуре микросервисов, вероятно, придется использовать их знания и опыт работы с этим сервисом, чтобы внести туда изменения. Возможно, даже придется подождать, пока они это сделают. Если функция находится в монолите, тогда с большой вероятностью я уже знаком с кодом или, по крайней мере, с его соглашениями.
Степень автономности команд зависит от уровней модульности и согласованности системы. Ни монолит, ни микросервисы ничего не гарантируют и не ограничивают в этом отношении. Следствием микросервисов будет модульность, а монолит будет способствовать большей согласованности.
Модульность монолита
Микросервисы по своей природе приводят к разбиению системы на модули. Монолиты, по сути, не очень помогают в этом, но, конечно же, и не мешают делать это вам.
Слабосвязанный, состоящий из модулей код с ограниченной функциональностью — хорошее решение, независимо от появления дополнительной сложности из-за сетевых границ между этими задачами.
Микросервисы не гарантируют хорошую модульность
Хотя микросервисы и обеспечивают модульность, нет никакой гарантии в качестве этой модульности. Микросервисы могут легко превратиться в тесно связанный «распределенный монолит», если не будет полностью продуман дизайн.
Если вы не сможете разбить монолит на эффективные модули, тогда сложно будет структурировать и успешную архитектуру микросервисов. Микросервисы содействуют модульной структуре, но они усложняют задачу.
Независимое развертывание
Одно из преимуществ микросервисов — независимое развертывание. Но необходимость организации нескольких развертываний в разных сервисах затрудняет выпуск новых функций.
Разбивка комплексных изменений
С монолитом вполне можно выделить комплексные и рискованные изменения в отдельные развертывания. Типичным примером является обеспечение прямой и обратной совместимости миграций с требованиями к производительности и развертываниям.
Очевидно, что это усложняет функциональность обновления точно так же, как и в микросервисах.
Управление зависимостями
В микросервисной архитектуре все сервисы независимы, но действительно ли это для вас важно?
В большом монолите довольно сложно управлять зависимостями. Разделение их на несколько небольших списков упрощает управление каждым из них, но может усложнить это для системы в целом.
В монолите рано или поздно вы столкнетесь с «нагромождением зависимостей» и конфликтом между двумя из них. Микросервисы не гарантируют отсутствие проблем, но они должны снизить вероятность их появления.
Следите за обновлениями зависимостей
Очевидно, что поддерживать ваши зависимости в актуальном состоянии желательно. Но на практике, как правило, что-то упускается из виду.
На самом деле использование новейших версий может усугубить эту проблему, поскольку одна зависимость будет двигаться вперед быстрее, чем другие связанные с ней. Поддержка в актуальном состоянии не означает обновление при первой возможности до самой последней версии.
Более простой и понятный код
Это преимущество микросервисов в лучшем случае фиктивное, а в худшем — обман.
Конечно, каждый сервис проще и понятнее. Но система в целом гораздо сложнее и труднее для восприятия. Вы не устраняете сложность, а лишь увеличиваете ее и переносите в другое место.
Модульность монолита
Для монолита не нужно вводить сетевые границы и изолированные процессы, чтобы код стал понятнее для инженеров. Монолит, разбитый на модули с четко определенными и ограниченными задачами, понять будет также легко, если не проще, чем разбитую на отдельные сервисы систему.
Проблемы вашего монолита
Если у вас все же остаются проблемы с монолитом, то вполне вероятно, что это и не совсем монолит.
Вполне возможно, что монолит остается ярким маяком качества кода, инструментария и модульности. Оказавшись в подобной ситуации, возможно, пришло время подумать и о микросервисах. Но это далеко не всегда так. Часто необходимо просто поработать над своим кодом.
Создавать программное обеспечение непросто. Очень сложно организовать большие системы с множеством динамичных компонентов, изменяющихся со временем.
Каюсь. И я строил беспорядочные монолиты. Не хочу обсуждать чьи-либо предпочтения. Но тех, кто надеется решить имеющиеся у монолита проблемы волшебным образом с помощью микросервисов, ждет разочарование.
Когда следует выбирать микросервисы?
Выбор между монолитом и микросервисами часто преподносится как два взаимоисключающих способа мышления. Старая и новая школы. Правильно или неправильно. Одно из двух.
Истина в том, что оба подхода допустимы при разных компромиссах. Правильный выбор в значительной степени зависит от контекста, с учетом широкого спектра соображений.
Мое мнение
Для новых, небольших и средних групп разработчиков монолит является выбором по умолчанию. Микросервисы остаются приемлемым вариантом, но для их использования у вас должны быть веские основания.
Средним и крупным командам следует рассмотреть возможность применения микросервисов, но с большой осторожностью и пониманием необходимости компромиссов.
НЛО прилетело и оставило здесь промокод для читателей нашего блога:
— 15% на все тарифы VDS (кроме тарифа Прогрев) — HABRFIRSTVDS.
Комментарии (11)
panzerfaust
04.10.2022 12:16+4У вашего рассказа как будто предусловие, что монолит у нас и так классный и от добра добра не ищут. Но я хотел бы, например, посмотреть на монолит, надо которым одновременно работают 40 разрабов и не знают печали. Если у вас там все настолько по солиду написано, то снимаю шляпу и признаю, что микросервисы вам не нужны.
aasten
05.10.2022 03:05+1Бывают случаи (как бы свидетелем был), когда разрабов больше чем 40 и проблемы тогда в проектах на микросервисах. Ну, я имею в виду, что микросервисы сами по себе вряд ли снимают такие проблемы.
Aknodx
04.10.2022 14:33Согласен, со многими бизнес задачами (в частности уровня предприятия) качественный монолит справится без каких либо проблем. А еще есть плюс у монолита на этапе прототипирования, а именно на этапе разработки функционального прототипа. Нескольким разработчикам вполне по силам в довольно короткие сроки построить работающий монолит (например на Java и Spring) чтобы самим посмотреть и другим показать как работают их идеи. Такой монолитный прототип можно попробовать, посмотреть на него с разных сторон, в том числе чтобы понять нужно ли выделять из него сервисы, и если нужно то какие именно, как они должны выглядеть, как ими управлять и т.д.
hippoage
04.10.2022 15:11В целом, можно представить себе схему когда у нас есть "монолит", который состоит из кучи библиотек (вместо отдельных сервисов).
Все-таки наличие таких библиотек необходимо (с какого-то размера), чтобы команды могли независимо делать эксперименты (если нет множества разных команд с разными целями и сроками, то и микросервисы, и библиотеки не нужны особо).
Таким образом, мы уходим от сетевых задержек. Какие при этом могут быть минусы?
- необходимость возможности старта всей системы на одном сервере: если используются локальные кеши, то такое не всегда возможно
- увеличенное время сборки, но при этом вся система стартует локально (что удобно для разработчиков)
- необходимо для одного запроса для снижения задержек использовать больше cpu/памяти/сети, чем есть на одном сервере
- вроде бы в таком случаем масштабирование проще, но когда есть совсем разные разпросы, то оно не эффективно (например, один запрос требует кучу данных в памяти, а другой запрос cpu, а третий по сути аркестрирует вызовы к базам)
- при большом количестве серверов и экспериментов придется довольно часто передеплоивать все, что, как ни крути, приводит к какому-то простою серверов и потенциальным ошибкам при обновлении
Т.е. да, в каких-то областях возможно не переходить на обычные микросервисы, а еще какое-то время оставаться на библиотечных микросервисах, но это каждый раз надо смотреть по месту. И, конечно, если у вас все и так хорошо без микросервисов, то не нужно их внедрять просто чтобы были.
Nilomar
04.10.2022 17:20+3Если библиотека микросервисов имеет достаточный уровень абстракции, то код очередного нового модуля будет одинаков, независимо от того монолит с библиотеками это или микросервисы. В обоих случаях разработчик помечает инжектом интерфейсы и дёргает их методы
Поэтому если отдел разработки не может построить кодовую базу монолита, он испытает точно такие же трудности и с кодовой базой микросервисов
ikostruba
04.10.2022 21:46+1Поддерживаю утверждение, что микросервисы имеют свою (и довольно высокую) цену. На моей старой работе новый владелец настоял на том, что старую систему надо выкинуть, и написать с нуля новую, с Растом и микросервисами. Набрали команду энтузиастов Раста с хорошим опытом на других языках, владелец привел знакомых архитекторов и понеслось. Спустя год работающий прототип так и не готов, написано больше десятка микросервисов, хитрым образом взаимодействующих между собой, запускать всё это умеет ровно один человек :)
А что вы думаете о другом модном тренде, serverless (AWS Lambda, GCP Cloud Functions и т.п.)?WALKER898
05.10.2022 13:43Почти один в один произошло и на моей прошлый работе. Разница была в том, что там были реальные проблемы с одним модулем монолита, но можно было было прекрасно вынести в отдельный сервис только этот модуль, так как он был довольно четко ограничен по функциональности и API можно было сделать очень просто.
Вместо этого CTO продавил идею "А давайте все распилим на микросервисы", хотя вся команда была против. Штат под это дело не расширили, в результате после года работы новая система так и не смогла по функциональности догнать старую, в проде работал чудовищный гибрид обоих, расходы на инфраструктуру почти удвоились.
smartello
05.10.2022 00:30+1Я работаю в Амазоне и моя команда отвечает в том числе за рендеринг информации о доставке. У нас был сервис и библиотека, которые делали одно и тоже, и мы заглушили сервис в начале этого года.
При всех плюсах этого подхода, описать боль деплоймента некоторых изменений достаточно сложно. Но самое интересное начинается когда что-то идёт не так, хотя ты ничего не менял. Мы уже полгода не можем найти причину падения доступности в одном регионе после того как одна из страниц сделала обновление зависимостей (нескольких тысяч разом).
VVitaly
05.10.2022 13:28Наиболее "круто" когда сотни микросервисов "упираются" в одну транзакционную "макробазу"... :-)
Homosum
05.10.2022 13:42+1Как бы помягче выразиться…
Данная статья демонстрирует искаженное восприятие микросервисной архитектуры. И что самое страшное, что она будет воздействовать на умы молодых людей, которые только встают на путь проектирования систем. Опытным специалистам с первых же абзацев видны эти искажения.
Одно лишь это предложение много чего стоит: «Вы серьезно перегрузите стек используемых технологий, что может затруднить для клиента взаимодействие с приложением.»
Вы серьезно думаете, что клиент должен знать о стеке используемых технологий? Расскажите, пожалуйста, КАК??? можно спроектировать приложение, чтобы стек используемых технологий затруднил взаимодействие с приложением.
Приведенные примеры отсутствия преимуществ микросервисов перед монолитом - это примеры НЕПРАВИЛЬНОГО проектирования.
ibKpoxa
Т.е. ответ нет.