Микросервисы. Не всё то золото, что хайп
Привет, меня зовут Владимир Кустиков, я — архитектор решений в e-Legion. И сегодня я хотел бы рассказать вам про микросервисы.
Наверное, я где-то неправ. А возможно, что у меня просто подгорело. Но в какой-то момент после запроса рассказать о том, в каких проектах я успешно применял микросервисы, моё терпение лопнуло. Ни в каких, понятно?! И это мой персональный повод для гордости. Если вам вдруг стало интересно, что ещё может рассказать этот странный безумец с пылающим взором, то у меня есть хорошая новость — ниже о микросервисах будет адаптированный под хаброформат рассказ с картинками. А если нет — смело закрывайте эту статью.
Для начала давайте синхронизируемся насчёт понятий, которые будут обсуждаться, а потом можно приступить и к самому обсуждению. Итак, микросервисы — что в имени тебе моём?
У меня есть две книги от Сэма Ньюмена: «Проектирование микросервисов» и «От монолита к микросервисам». Они слегка нелогичны, так как вторая книга является по сути предтечей первой, хотя и выпущена сильно позже. Но особый интерес во второй книге для меня вызвали комментарии переводчика. Он ВНЕЗАПНО взял и перевёл наши родненькие «микросервисы» как «микрослужбы», и по всему тексту книги ни одного упоминания о микросервисах не оставил. И наверное, моему возмущению такой отсебятиной не было бы предела, если бы он там же не объяснил свою позицию. А она крайне логична — слово «служба» несёт в себе мощный семантический посыл, который оказывается утраченным при другом переводе. Так что, поразмыслив, я пришёл к выводу, что этот вариант мне даже нравится больше. Действительно, легко представить себе некого служивого, который умеет нести свою службу, от и до, и ни шага в сторону (привет, контракты!). И тогда микрослужбы — это мальчики-с-пальчики, которые вроде и ростом невелики, и помощи от них немного, но при необходимости могут и Гулливера нитками к земле привязать.
Казалось бы, после такого перевода необходимость в определении микросервиса отпадает сама собой. Но есть ещё один вариант от Avery Pennarun, которым невозможно не поделиться:
Микросервисы — это самая экстремально возможная реакция на монолиты.
Но так ли плох монолит, чтобы на него требовалось реагировать, да ещё и экстремально? Давайте разбираться, что там у него с порохом и пороховницами.
Внимание, вопрос на засыпку. Знаете ли вы, чем отличается монолит от микросервисов?
Правда, монолит красивее? 😊 Хотя о вкусах не спорят, но как минимум на этой картинке он выглядит проще. Да собственно, так оно и есть. Монолит в разы проще, но при этом предоставляет массу возможностей, от которых приходится отказываться, переходя на микросервисную архитектуру. Ну вот, навскидку:
Не нужно думать о куче взаимосвязей — весь проект полностью у тебя перед глазами в любимой IDE. И он либо соберётся и запустится — либо нет.
Разработчики могут протянуть любое сквозное изменение через всю систему (UI-Application-Database), так как владеют ей полностью.
Есть множество методик тестирования монолита, отточенных в тысячах проектов.
Часто развёртывание заключается в переносе файлов на единственный сервер.
И даже нарисовать монолит бывает проще. Вот как симпатично он может выглядеть в гексагональной архитектуре.
Не подумайте, я не настолько люблю монолиты, чтобы эта любовь розовой пеленой застилала мне глаза. Вовсе нет, у монолитов есть свои недостатки, которые могут быть в определённых условиях настолько весомыми, что на них потребуется самая экстремально возможная реакция. 😊
- Сложно разрабатывать разнородную функциональность.
- Сложно организовать работу разных команд.
- Каждое изменение требует полного переразвёртывания.
- Зависимость от постепенно устаревающего стека.
- Зависимость от единственного физического узла.
- Невозможно масштабировать функциональность отдельно.
Трудно поспорить, что это действительно критически важные недостатки. Однако большинство из них не требует радикальных реакций. Более того, на мой взгляд, большая часть проблем, возникающих на проектах, может (и должна) решаться в рамках теплых ламповых монолитов, но с небольшой щепоткой стероидов.
Посмотрите на рисунок ниже. Видите суслика? А его там и нет, так как не умеют суслики рыть норы в форме правильного куба, тем более, что это не простой куб, а самый настоящий куб масштабирования.
Чтобы разобраться во всём этом многобукофии и многоцифрии, предлагаю сразу обратить своё внимание на левый нижний угол куба с гордой цифрой «ноль». Этот угол — стандартное представление о монолитах — такие решения «сами в себе», запускаемые в единственном экземпляре и обрабатывающие весь поток поступающих данных. Но, к счастью, жизнь монолита не обрывается в этом углу, у него есть ещё целых три оси масштабирования:
- Ось X — распределение нагрузки между несколькими идентичными экземплярами.
- Ось Y — разделение приложения на функциональные сервисы.
- Ось Z — выполнение запросов в зависимости от их атрибутов.
Нетрудно заметить, что монолит может масштабироваться по осям X и Z, не разваливаясь при этом на микросервисы, то есть может сначала развернуться на несколько инстансов за балансировщиком нагрузки, а потом ещё и распределить нагрузку по значениям атрибутов (другими словами, шардироваться). А вот если уже и это не помогает, тогда можно взглянуть и на микросервисы. Украдкой, с опаской, но взглянуть.
Прежде чем всё-таки перейти на микросервисы, ответьте на следующие вопросы:
- Ваш монолит разбит на связные модули с минимальным количеством внешних взаимодействий?
- Вы рассмотрели все потенциальные варианты масштабирования монолита?
- Не подойдёт ли для ваших задач компромиссное решение, например, модульный и/или распределённый монолит или цитадель?
Кстати, о цитаделях. На мой взгляд это замечательный концепт с не менее замечательным названием. Если вкратце, то это монолит (сама цитадель) с вынесенной из него обособленной логикой (форпосты). При этом форпосты выполняют все те задачи, под которые обычно нанимают микросервисы. Думаю, одна картинка лучше тысячи слов.
Смотрите, монолит практически полностью остался в первозданном виде. Но это только на первый взгляд. Предвидя новые вызовы или отвечая на уже существующие, монолит выделил из себя форпост — сервис, который должен решить те задачи, с которыми по объективным причинам цельному неповоротливому решению справиться значительно сложнее. Это могут быть проблемы неравномерности нагрузки, особенностей развёртывания, особенностей технологического стека, организационных проблем — по сути тех проблем, ради решения которых и призывают «нас наш, нас новый мир построить», предварительно разрушив всё до основанья.
При таком подходе в цитадели остаётся цельно и связно функционирующая предметная логика приложения, прикрытая от внешнего окружения форпостами, имеющими своё независимое внутреннее самоуправление. По собственному опыту могу сказать, что часто подобная архитектура решает все те проблемы, ради которых пытаются перейти на микросервисы, причём делает это наиболее естественным, простым и безопасным для разработки и бизнеса способом.
Но я подозреваю, что может возникнуть резонный вопрос — почему я всеми силами пытаюсь склонить читателей к неиспользованию микросервисов? Почему настолько категоричен в отношении виновников нашего торжества (читай, статьи)?
При всей простоте идеи микросервисы — крайне сложная вещь, которая несёт с собой другие сложные вещи. Самое важное, что необходимо держать в голове следующее: микросервисные системы — это распределённые системы со всеми вытекающими последствиями. Если при прочтении предыдущего предложения ваши волосы не встали дыбом, то могу вас только поздравить. Либо с тем, что вы настолько умны (и я вам очень сильно завидую), либо с тем, что у вас впереди множество открытий чудных.
Вообще, существует несколько преимуществ перехода на микросервисы:
- Делает возможными непрерывную доставку и развёртывание крупных, сложных систем.
- Код небольшой и простой в обслуживании.
- Независимое развёртывание.
- Независимое масштабирование.
- Автономность команд разработки.
- Позволяет экспериментировать с технологиями.
- Лучшая изоляция неполадок.
Но если внимательно присмотреться, то часть из них присутствует и в монолитах. Давайте уменьшим монолит в миллион раз, и что получим? Микромонолиты, раскиданные по сети со всеми вытекающими преимуществами и проблемами.
- Сложно подобрать подходящее разбиение на сервисы.
- Сложность распределённых систем затрудняет разработку, тестирование и развёртывание.
- Развёртывание функциональности, охватывающей несколько сервисов, требует тщательной координации.
- Сложно определить момент, когда переход на микросервисы станет обоснованным.
- Самая большая боль, как я уже сказал раньше — это то, что система переходит в класс распределенных, а там ох сколько проблем. Но как говорится, мыши плакали, кололись, но продолжали хайповать. И конечно же, неразрешимых проблем нет, при большом желании можно и JavaScript сделать серверным языком. Желание было, возможности тоже — вот и решения нашлись. Возможно, благодаря этим решениям и поддерживается технический прогресс. Так что не всё то плохо, что кажется таким. И я для себя выделил некоторые проблемы и их решения, которые хоть как-то можно привязать к микросервисам, причём не всегда будут прослеживаться причинно-следственные и пространственно-временные связи, но определённая логика в этом есть. Вот, смотрите:
— Координация множества сервисов:
Ну ок, вы всё-таки решились. Я сдаюсь. Микросервисы — ваше всё, и возражений не принимается. Как сделать хороший микросервис? Да практически так же, как и хороший модульный монолит. Но есть ещё несколько пунктиков:
- Его выделение обосновано (есть спец-команда, спец-требования, спец-ограничения, спец-циалисты).
- У него сильное внутреннее сцепление и слабая внешняя связанность.
- Он выполняет четко определённую функциональность.
- Есть настроенное внешнее окружение и шаблон сервиса, который умеет в этом окружении жить и взаимодействовать.
- Интеграции — обычно хороший вариант для микросервиса.
А у меня на этом всё, надеюсь, эта статья будет для вас полезной.