Микросервисы: преимущества, недостатки, когда использовать
Что такое микросервисы?
Микросервисы — это независимо выпускаемые сервисы, которые моделируются на основе бизнес-домена.
Микросервисные архитектуры в большинстве случаев избегают использования общих баз данных; вместо этого каждый микросервис инкапсулирует свою собственную базу данных, где это необходимо.
Наличие четких, стабильных границ обслуживания, которые не меняются при изменении внутренней реализации, приводит к тому, что системы имеют более слабую связанность (coupling) и более сильную сплоченность (cohesion).
Ключевые концепции микросервисов
- Independent deployability. Слабо связанные сервисы со стабильными интерфейсами — контрактами.
- Modeled Around a Business Domain. Развертывание фичи, требующей изменений в нескольких микросервисах, обходится дорого → архитектура системы должна максимально отражать бизнес-задачи, а не технологические отделы. Потому что задачи бизнеса не могут быть решены только одним отделом, нужна кроссфункциональная команда.
- Owning Their Own State. Не шарить базы данных. Никогда. Если что-то надо от микросервиса, то нужно идти и спросить его.
- Size. Размер микросервиса — чтобы уместился в твоей голове.
- Flexibility. Важно количество микросервисов. Растёт сложность. Внедрять микросервисы постепенно.
Монолит
Note
Монолит — валидный выбор. Следует обосновывать использование микросервисов.
Монолиты могут упростить повторное использование кода внутри самого монолита.
Если требуется переиспользовать код в распределенной системе, то можно:
- копировать такой код;
- выделять его в библиотеки;
- выделять общие функции в отдельный микросервис.
Single-process monolith
Весь код деплоится как single process. У вас может быть несколько экземпляров этого процесса из соображений надежности или масштабирования, но в основном весь код упакован в один процесс.
Modular monolith
Modular monolith — вариация, когда single process содержит отдельные модули. Каждый модуль может работать отдельно, но все еще должны быть скомбинированы вместе для деплоя.
На схеме приведены несколько модулей в одной связке, работающие с одной БД:
Есть ещё вариант, где эти же модули работают со своими отдельными БД:
Distributed monolith
Распределенный монолит — это система, состоящая из нескольких сервисов, но по какой-то причине вся система должна быть развернута вместе.
Распределенный монолит имеет все недостатки распределенной системы и недостатки однопроцессного монолита, не имея достаточно плюсов того и другого.
Преимущества микросервисов
- Технологическая неоднородность (гетерогенность):
- Позволяет использовать подходящие инструменты для каждой задачи вместо одного универсального.
- Можно быстрее абсорбировать новые технологии. Например, сначала использовать на одном наименее критичном микросервисе.
- Надежность:
- Ключевая концепция обеспечения надежности — изоляция доменов отказа.
- С монолитной системой мы можем работать на нескольких машинах, чтобы уменьшить вероятность сбоя, но с микросервисами мы можем создавать системы, которые обрабатывают полный сбой некоторых из составляющих сервисов и пропорционально снижают функциональность.
- Масштабируемость:
- Можно масштабировать ресурсы только тех частей системы, которые действительно в них нуждаются.
- Простота развертывания:
- Изменение одной строки в монолитном приложении из миллиона строк требует, чтобы все приложение было развернуто, чтобы выпустить изменение. Придется протестировать на регрессию все приложение.
- С микросервисами деплой осуществляется быстрее и чаще.
- Организационное выравнивание:
- С микросервисами можно минимизировать кодовую базу отдельных частей и уменьшить размеры команд → выше продуктивность.
- Компонуемость:
- Открываются возможности для повторного использования функциональности.
- С помощью микросервисов мы позволяем использовать нашу функциональность по-разному для разных целей.
Болевые точки микросервисов
- Developer Experience:
- С ростом числа компонентов системы становится сложнее запустить её локально на машине разработчика, чтобы проверить, как всё работает.
- Это может стать еще более сложным, если вы используете облачные сервисы, которые не можете запустить локально.
- Technology Overload:
- Микросервисы могут предоставить вам возможность для каждого микросервиса быть написанным на другом языке программирования, запускаться в другой среде выполнения или использовать другую базу данных — но это опции, а не требования.
- Вокруг микросервисов создано много технологий → см. CNCF Cloud Native Interactive Landscape. Пропускная способность команды, затрачиваемая на попытки разобраться во всех этих новых технологиях, сократит время, которое у вас есть на фактическую доставку функций вашим пользователям.
- Cost:
- Микросервисы — плохой выбор для организации, которая в первую очередь заинтересована в снижении затрат, поскольку менталитет сокращения затрат — когда ИТ рассматривается как центр затрат, а не центр прибыли — будет постоянно тормозить получение максимальной отдачи от этой архитектуры.
- С другой стороны, микросервисы могут помочь вам заработать больше денег, если вы сможете использовать эти архитектуры для охвата большего числа клиентов или параллельной разработки дополнительных функций.
- Reporting:
- Нет единой БД, по которой можно делать join'ы. Собрать отчет из распределенной системы гораздо сложнее, потому что данные разбросаны по разным логически изолированным схемам.
- Может потребоваться внедрение современных подходов streaming for real-time reporting. Или может потребоваться публикация данных со всех микросервисов в единую reporting БД (data lake).
- Monitoring and Troubleshooting:
- В микросервисной архитектуре связи могут быть нелинейны и их много.
- В монолитной системе, если наш CPU утилизирован на 100% в течение длительного времени, мы знаем, что это большая проблема. Можем ли мы сказать то же самое о микросервисной архитектуре с десятками или сотнями процессов? Нужно ли нам будить кого-то в 3 часа ночи, когда только один процесс утилизировал CPU на 100% ?
- Security:
- Больше коммуникации по сети → нужно защищать сетевое взаимодействие.
- Авторизация эндпоинтов.
- Testing:
- В микросервисной архитектуре сложно производить end-to-end тестирование, потому что их скоуп становится очень большим.
- Теперь нам нужно будет запускать тесты в нескольких процессах, все из которых должны быть развернуты и соответствующим образом настроены для тестовых сценариев. Мы также должны быть готовы к ложноотрицательным результатам, которые возникают, когда проблемы с окружающей средой, такие как отказ экземпляров службы или сетевые тайм-ауты при неудачных развертываниях, приводят к сбою наших тестов.
- Latency:
- Обработка, которая ранее могла выполняться локально на одном процессоре, теперь может быть разделена на несколько отдельных микросервисов. Информация, которая ранее передавалась только в рамках одного процесса, теперь нуждается в сериализации, передаче по сети и десериализации. Все это может привести к увеличению latency вашей системы.
- Data Consistency:
- Не получится использовать транзакции.
- Трудно обеспечить консистентность данных → см.транзакции, ACID, уровни изоляции, CAP-теорема.
Должен ли я использовать микросервисы
❌ Не подходит для:
- Плохой выбор для новых продуктов или стартапов.
- Более целесообразно подождать, пока модель предметной области стабилизируется, прежде чем пытаться определить границы сервиса.
- На требование по масштабированию не надо обращать внимание. Будет ещё много пивотов и то, что задумывалось изначально, преобразуется до неузнаваемости.
- В стартапах и некоторых других компаниях вечно не хватает разработчиков. А для микросервисов их нужно больше → “microservice tax”. И чем меньше команда, тем более заметен этот налог.
- Не подходит для компаний, создающих ПО, которое будет деплоиться и управляться их потребителями.
✅ Подходит для:
- Больших команд. Когда нужно, чтобы много разработчиков не мешали друг другу при работе над одной и той же системой. Т.е. для команды из 5 разработчиков микросервисы не нужны. А вот для 100 разработчиков уже обоснованны.
- Software as a Service (SaaS) приложений.
- Для проектов, которые предполагается деплоить в публичные облака.