Микросервисы. Не всё то золото, что хайп +68


Привет, меня зовут Владимир Кустиков, я — архитектор решений в e-Legion. И сегодня я хотел бы рассказать вам про микросервисы.

Наверное, я где-то неправ. А возможно, что у меня просто подгорело. Но в какой-то момент после запроса рассказать о том, в каких проектах я успешно применял микросервисы, мое терпение лопнуло. Ни в каких, понятно?! И это мой персональный повод для гордости. Если вам вдруг стало интересно, что еще может рассказать этот странный безумец с пылающим взором, то у меня есть хорошая новость — ниже о микросервисах будет адаптированный под хаброформат рассказ с картинками. А если нет — смело закрывайте эту статью.

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

У меня есть две книги от Сэма Ньюмена: «Проектирование микросервисов» и «От монолита к микросервисам». Они слегка нелогичны, так как вторая книга является по сути предтечей первой, хотя и выпущена сильно позже. Но особый интерес во второй книге для меня вызвали комментарии переводчика. Он ВНЕЗАПНО взял и перевел наши родненькие «микросервисы» как «микрослужбы», и по всему тексту книги ни одного упоминания о микросервисах не оставил. И наверное, моему возмущению такой отсебятиной не было бы предела, если бы он там же не объяснил свою позицию. А она крайне логична — слово «служба» несет в себе мощный семантический посыл, который оказывается утраченным при другом переводе. Так что, поразмыслив, я пришел к выводу, что этот вариант мне даже нравится больше. Действительно, легко представить себе некого служивого, который умеет нести свою службу, от и до, и ни шага в сторону (привет, контракты!). И тогда микрослужбы — это мальчики-с-пальчики, которые вроде и ростом невелики, и помощи от них немного, но при необходимости могут и Гулливера нитками к земле привязать.

Казалось бы, после такого перевода необходимость в определении микросервиса отпадает сама собой. Но есть ещё один вариант от Avery Pennarun, которым невозможно не поделиться:

Микросервисы — это самая экстремально возможная реакция на монолиты.

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

Внимание, вопрос на засыпку. Знаете ли вы, чем отличается монолит от микросервисов?

А если вот так?

Правда, монолит красивее? ???? Хотя о вкусах не спорят, но как минимум, на этой картинке он выглядит проще. Да, собственно, так оно и есть. Монолит в разы проще, но при этом предоставляет массу возможностей, от которых приходится отказываться, переходя на микросервисную архитектуру. Ну вот, навскидку:

  • Просто разрабатывать.

Не нужно думать о куче взаимосвязей — весь проект полностью у тебя перед глазами в любимой IDE. И он либо соберется и запустится — либо нет.

  • Легко вносить сквозные изменения.

Разработчики могут протянуть любое сквозное изменение через всю систему (UI-Application-Database), так как владеют ей полностью.

  • Просто тестировать.

Есть множество методик тестирования монолита, отточенных в тысячах проектов.

  • Просто развертывать.

Часто развертывание заключается в переносе файлов на единственный сервер.

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

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

Вот эти «граждане»:

  • Сложно разрабатывать разнородную функциональность.

  • Сложно организовать работу разных команд.

  • Каждое изменение требует полного переразвёртывания.

  • Зависимость от постепенно устаревающего стека.

  • Зависимость от единственного физического узла.

  • Невозможно масштабировать функциональность отдельно.

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

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

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

  • Ось X — распределение нагрузки между несколькими идентичными экземплярами.

  • Ось Y — разделение приложения на функциональные сервисы.

  • Ось Z — выполнение запросов в зависимости от их атрибутов.

Нетрудно заметить, что монолит может масштабироваться по осям X и Z, не разваливаясь при этом на микросервисы, т.е. может сначала развернуться на несколько инстансов за балансировщиком нагрузки, а потом еще и распределить нагрузку по значениям атрибутов (другими словами, шардироваться). А вот если уже и это не помогает, тогда можно взглянуть и на микросервисы. Украдкой, с опаской, но взглянуть. 

Прежде, чем все-таки перейти на микросервисы, ответьте на следующие вопросы:

  • Ваш монолит разбит на связные модули с минимальным количеством внешних взаимодействий?

  • Вы рассмотрели все потенциальные варианты масштабирования монолита?

  • Не подойдет ли для ваших задач компромиссное решение, например, модульный и/или распределенный монолит или цитадель?

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

Что здесь интересного?

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

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

Но я подозреваю, что может возникнуть резонный вопрос — почему я всеми силами пытаюсь склонить читателей к неиспользованию микросервисов? Почему настолько категоричен в отношении виновников нашего торжества (читай, статьи)?

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

Вообще, существует несколько преимуществ перехода на микросервисы:

  • Делает возможными непрерывную доставку и развертывание крупных, сложных систем.

  • Код небольшой и простой в обслуживании.

  • Независимое развертывание.

  • Независимое масштабирование.

  • Автономность команд разработки.

  • Позволяет экспериментировать с технологиями.

  • Лучшая изоляция неполадок.

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

Ну а теперь о болях:

  • Сложно подобрать подходящее разбиение на сервисы.

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

  • Развертывание функциональности, охватывающей несколько сервисов, требует тщательной координации.

  • Сложно определить момент, когда переход на микросервисы станет обоснованным.

Самая большая боль, как я уже сказал раньше — это то, что система переходит в класс распределенных, а там ох сколько проблем. Но как говорится, мыши плакали, кололись, но продолжали хайповать. И конечно же, неразрешимых проблем нет, при большом желании можно и JavaScript сделать серверным языком. Желание было, возможности тоже — вот и решения нашлись. Возможно, благодаря этим решениям и поддерживается технический прогресс. Так что не все то плохо, что кажется таким. И я для себя выделил некоторые проблемы и их решения, которые хоть как-то можно привязать к микросервисам, причем не всегда будут прослеживаться причинно-следственные и пространственно-временные связи, но определенная логика в этом есть. Вот, смотрите:

  • Автономное развертывание

o   Контейнеры, Docker, Kubernetes (K8s)

  • Сетевые вызовы

o   Сериализованные очереди, предохранители, дублирование соединений и сервисов

  • Координация множества сервисов

o   Оркестрация, хореография, Service Mesh (istio, linkerd, envoy)

  • Пользовательский интерфейс

o   API Gateway, фрагменты, микрофронтенды, BFF

  • Безопасность

o   OpenID, Single Sign-On (SSO), JWT

  • Распределенные транзакции

o   Саги, консенсус

  • Генерация отчетов

o   Репликация, CQRS

  • Разные рабочие окружения

o   Сервера конфигураций, решения для развертывания

o   Канареечные и сине-зеленые выпуски

o   DevOps-инженеры

  • Тестирование

o   Тесты на основе запросов потребителей (CDC-тесты) вместо сквозных

  • Журналирование

o   Сквозные идентификаторы

Ну ок, вы все-таки решились. Я сдаюсь. Микросервисы — ваше всё, и возражений не принимается. Как сделать хороший микросервис? Да практически так же, как и хороший модульный монолит. Но есть еще несколько пунктиков:

  • Его выделение обосновано (есть спец-команда, спец-требования, спец-ограничения, спец-циалисты).

  • У него сильное внутреннее сцепление и слабая внешняя связанность.

  • Он выполняет четко определенную функциональность.

  • Есть настроенное внешнее окружение и шаблон сервиса, который умеет в этом окружении жить и взаимодействовать.

  • Интеграции — обычно хороший вариант для микросервиса.

А у меня на этом всё, надеюсь, эта статья будет для вас полезной.




К сожалению, не доступен сервер mySQL