Найти тему

Монолиты против Микросервисов

Оглавление

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

В своей книге «Sapiens» историк Юваль Ной Харари посвящает несколько начальных глав объяснению перехода людей от образа жизни охотников-собирателей к фермерскому.

При этом он развенчивает несколько мифов о жизни доисторических людей.

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

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

Однако у образа жизни фермеров был один главный плюс: они производили больше еды, что позволяло поддерживать создание более крупных сообществ. Другими словами, жизнь была никчёмной практически во всём, но теперь она стала масштабируемой!

Вам это ничего не напоминает?

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

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

Пример таких весьма противоречивых вариантов - это выбор монолитов или микросервисов в качестве стратегии разработки ИТ систем.

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

Итак, давайте разберём:

  • 📖 Определения — Соберём их все на одной странице.
  • ✏️ Дизайн системы — В чем различия между подходами?
  • 📈 Масштабируемость — правда ли, что микросервисы масштабируются лучше, чем монолиты? (Спойлер: не всё так просто).
  • 🚚 Продуктивность — Изменяется ли ваш процесс разработки в зависимости от вашей архитектуры? Ещё бы!
  • 🔍 Примеры из практики — три реальных кейса развивающихся монолитов и микросервисов.
  • ⚖️ Как выбрать — Подведем итоги и выясним, что лучше для вас.

Поехали!

📖Определения

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

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

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

Как же сделать выбор между одним и другим? Начнём с дизайна системы 👇

✏️ Дизайн системы

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

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

Когда задача не ясна и быстро меняется, использование архитектуры микросервисов может привести к значительным затратам на их переделку. Однако, в противовес этому монолиты могут быть менее дорогостоящими в случае неправильной абстракции, так как их проще “допилить”. Чем сложнее границы задачи, тем более сложной будет ее проектирование. Поэтому микросервисы могут быть опасными для стартапа, если границы задач еще не определены.

📈 Масштабируемость

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

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

Краткосрочная масштабируемость

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

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

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

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

Долгосрочная масштабируемость

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

Монолит может проще масштабироваться вертикально в долгосрочной перспективе.

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

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

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

Обслуживание всего этого требует большого количества времени и ресурсов со стороны инженеров. Это может привести к тому, что затраты на обслуживание превысят все преимущества, которые можно получить от оптимизации сервиса.

А что насчёт безсерверных сервисов (serverless)?

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

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

Как правило, чем на большее количество сервисов разбита ваша система, тем жёстче её архитектура и тем труднее перестроить её в будущем.

🚚Производительность

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

Непрерывная поставка

Развёртывание монолита, как правило, дольше и рискованнее, поскольку компоненты, скрипты и т.п. должны быть установлены одновременно.

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

Это классическая проблема для общих промежуточных сред (тест, пре-прод и т.п.).

Микросервисы обеспечивают изолированные тесты и релизы, что обычно является преимуществом непрерывной поставки.

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

Два года назад мы перешли от монолита к более лёгкой версии монолита смешанного с микросервисами.

В этом выборе нет никакого хайпа. Это было просто лучшее решение, которое мы могли себе представить. Наш продукт — это ERP - система для упаковочной промышленности. В условиях того, что некоторые называют индустрией 4.0, нам пришлось создавать интерфейсы с системами конвейерных лент, чтобы позволить им оптимизировать маршрутизацию продукции.

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

Мы решили сделать микросервис для каждой конвейерной системы, чтобы иметь возможность обновлять их, не останавливая всё на фабриках.

С тех пор мы начали делать то же самое для наших интерфейсов с производственными машинами.

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

Таким образом, например совсем недавно реструктурировалась Coinbase, а Amazon управлялась так … почти всегда. В 2002 году Джефф Безос разослал сотрудникам следующее письмо, которое стало известно как «Мандат API»:

1. Отныне все команды будут предоставлять свои данные и функции через сервисные интерфейсы.

2. Команды должны общаться друг с другом через эти интерфейсы.

3. Не будет разрешено никаких других форм межпроцессного взаимодействия: никаких прямых ссылок, никакого прямого чтения хранилища данных другой команды, никакой модели с общей памятью, никаких прочих лазеек. Единственная разрешённая связь — через вызовы сервисного интерфейса по сети.

4. Неважно, какую технологию они используют. HTTP, Corba, Pubsub, собственные протоколы — не имеет значения.

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

6. Любой, кто этого не сделает, будет уволен.

7.Спасибо; хорошего дня!

Конечно, мы можем согласиться с мандатом Безоса и историей с Coinbase, но есть два нюанса. Вы только выиграете от такой организации, если:

1. Ваша команда довольно большая

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

2. Ваши сервисы действительно независимы и могут быть развернуты по отдельности. Однако, если вам необходимо координировать одновременный выпуск, то лучше использовать "монолитное развёртывание", так как это позволит избежать возможных конфликтов между сервисами и обеспечит более стабильную работу продукта.

🔥 Отказоустойчивость

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

Хотя это верно, также верно и то, что ничто не мешает вам проектировать монолитные компоненты, которые столь же слабо связаны и изолированы. Это особенно ярко проявляется в случае ошибок выполнения (runtime errors): их обработка для сетевых сервисов, возможно сложнее, чем для компонентов отдельного сервиса.

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

🔨Обслуживание

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

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

  • Зависимости — нужно координировать множество зависимостей и версий в нескольких местах вместо одного.
  • Мониторинг —Следить за десятками разнообразных сервисов может оказаться сложнее, чем за одним, потому что у каждого из них есть свой собственный профиль загрузки, процессор и память.
  • Обнаруживаемость — для того, чтобы сервисы могли быть обнаружены и использованы другими людьми, может потребоваться больше работы с документацией, чем для компонентов в монолите.

🔍Примеры из практики

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

📑 Segment: Прощай, микросервисы — Segment перешел от монолита к микросервисам и обратно и написал невероятную статью о проблемах, возможностях и уроках, извлеченных на этом пути.

📑 Shopify: деконструкция монолита — Shopify применили другой подход и постепенно превратили свой монолит в модульный. Прикрепленная статья содержит множество подробностей о том, как они управляли зависимостями и рамками для обеспечения модульности.

📑 Масштабирование SaaS до 3 миллионов долларов в год на основе монолита — подробный отчет Никиты Логачёва, вице-президента по проектированию в Omniscope, о технических вопросах и решениях, с которыми он столкнулся как технический директор, которому нужно было многократно увеличить масштабы SaaS-бизнеса.

⚖️ Как выбрать

Обратимся к закону Галла:

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

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

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

-2

Случай Shopify поучителен, поскольку он рассматривает две основные координаты: модульность и единицы развертывания.

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

2) Единицы развёртывания — чем больше вещей вам нужно развернуть, тем сложнее становится ваша система. При прочих равных, вы предпочтёте чтобы число единиц развертывания оставалось как можно меньшим.

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

-3

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

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

У вас есть история о ваших монолитах или микросервисах? Расскажите в комментариях!👇