Обложка статьи «Нужны ли вашему проекту микросервисы? Вопросы, которые помогут разобраться»

Нужны ли вашему проекту микросервисы? Вопросы, которые помогут разобраться

На основе «STOP!! You don’t need Microservices»

Автор Алексей Морозов

На дворе 2020 год, и весь Интернет только и делает, что обсуждает бесчисленные достоинства микросервисов. Истории успеха правдивы, микросервисы хороши для своих задач. Вот только, как и любая модная идея, они кажутся «серебряной пулей», решающей все проблемы на свете и подходящей для абсолютно любого проекта. Это не совсем так, и прежде чем дробить свой монолитный проект на микросервисы, надо задать себе несколько вопросов и убедиться, что они вам нужны.

У вас действительно огромный монолит?

Микросервисы всегда противопоставляют «огромным монолитным системам», и ключевое слово тут «огромная». Прежде всего нужно понять, так ли ваша система велика, что её имеет смысл дробить на части. Микросервисы по определению — набор отдельных сервисов, каждый из которых выполняет свою задачу. В идеале, каждый из них должен быть независимым от остальных.

Это означает, что у микросервиса есть предел сложности (и в количестве строк, и в вычислительных ресурсах), ниже которого он не будет работать. Грубо говоря, модуль в составе монолита может ограничиться несколькими классами, а микросервис (каждый!) обязан предоставлять API, получать данные из сети, обеспечивать их валидацию и хранение, самостоятельно вести логи и т. д. Из-за этого стоимость разработки для микросервисов и монолитов выглядит примерно так:

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

Вам действительно нужно масштабировать отдельные компоненты?

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

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

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

Возникают ли транзакции, в которых участвует несколько сервисов?

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

REST-сервисы по определению не должны иметь внутреннего состояния, так что им лучше не вступать в сложные операции на несколько сервисов. В мире высокой нагрузки двухфазные коммиты (2PC) — ненужное зло, а паттерн SAGA только добавит сложности.

Часто ли данные передаются между сервисами?

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

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

Что ещё нужно учитывать?

  • Дополнительная сложность. Да, вся идея микросервисов в том, что каждый из них в отдельности становится проще и понятнее. Но систему в целом сложнее деплоить и поддерживать.
  • Дополнительная стоимость. Монолитная система может хоститься на единственной виртуальной машине или в контейнере, а микросервисы (в идеале) хостятся по отдельности. Да, виртуалки будут не такими большими, но их будет много, и скорее всего это будет дороже.
  • DevOps. Это можно считать и за достоинство, и за недостаток, но с микросервисами вам однозначно понадобится DevOps-команда. С одной стороны — её в любом случае неплохо иметь, а с другой — она вам прямо сейчас по карману?
  • Неизбежная связность. Некоторые задачи в вашем проекте наверняка плотно связаны друг с другом по своей природе (тот же учёт сотрудников и учёт зарплат, например). Любая попытка их разделить ради соответствия архитектуре скорее всего закончится печально.
  • Неопытная команда. Это, конечно, проблема для любого проекта. Но в погоне за абстрактным идеалом «микросервисов» можно получить чудовищно плохую архитектуру. Когда сервисы перестанут работать, если их деплоить в неправильном порядке, или когда падение одного сервиса обрушит все остальные, будет уже слишком поздно.
  • Сложность тестирования. Для монолита тесты обычно запускаются одной командой, а для тестирования набора взаимосвязанных сервисов нужна отдельная система.
  • Совместимость данных. Согласование форматов данных в пределах одной команды — это совсем не то же самое, что согласование между несколькими командами, которые к тому же могут находиться на разных концах планеты и/или программировать на разных языках. На обсуждение спецификаций неизбежно потребуются дополнительные время и силы.
  • Поддержка старого кода. Давайте честно: большинство систем не создаётся с нуля. Новая архитектура — это хорошо, но она усложняет взаимодействие с уже имеющимся кодом, и неплохо бы убедиться, что ваш новенький микросервисный фреймворк будет нормально работать с приложением, которое уже 20 лет как крутится на IBM AIX.
  • Отладка и мониторинг. Отдельные системы — это в том числе и отдельные логи. Найти ошибку где-то в пяти раздельных лог-файлах сложнее, чем в одном.

Значит ли это, что не стоит пользоваться микросервисами? Нет. История Netflix вдохновила многих, и вполне заслуженно. Uber, SoundCloud и Amazon используют микросервисы и делают с их помощью вещи, которые раньше казались невозможными. Но это не означает, что микросервисы — идеальная архитектура, подходящая для всех проектов.

Многим программистам хочется использовать все крутые идеи, которые они увидели. Но тем и отличаются хорошие программисты, что они понимают разницу между «крутыми идеями» и «идеями, подходящими в данном конкретном случае».

Вакансии в тему: