Какие микросервисные паттерны ты знаешь?

Ответ

При проектировании микросервисных архитектур я применяю следующие ключевые паттерны для решения типичных проблем распределенных систем:

  • API Gateway: Единая точка входа для клиентов, которая занимается маршрутизацией, аутентификацией, ограничением скорости запросов (rate limiting) и иногда агрегацией данных из нескольких сервисов. На практике использовал Kong и написание кастомных шлюзов на Go.
  • Service Discovery & Registry: Паттерн для динамического обнаружения сетевых расположений сервисов. Работал с Consul и etcd, где сервисы при старте регистрируются, а при обращении к другим сервисам клиент сначала запрашивает их актуальный адрес у registry.
  • Circuit Breaker («Предохранитель») : Защищает систему от каскадных сбоев. При повторных ошибках вызова удаленного сервиса «предохранитель» размыкается, и дальнейшие вызовы мгновенно завершаются ошибкой, давая целевой системе время на восстановление. Реализовывал с помощью библиотеки Resilience4j.
  • Saga: Паттерн для управления распределенными транзакциями. Вместо одной ACID-транзакции используется последовательность локальных транзакций в разных сервисах, каждая из которых публикует событие для запуска следующего шага. При ошибке выполняются компенсирующие транзакции (rollback).
  • CQRS (Command Query Responsibility Segregation): Разделение моделей для записи (команды) и чтения (запросы). Это позволяет независимо масштабировать и оптимизировать операции чтения, например, используя денормализованное представление данных в отдельной БД.
  • Event Sourcing: Хранение состояния приложения как последовательности событий. Все изменения фиксируются в immutable event store. Это дает полный аудит, позволяет воспроизводить состояние на любой момент времени и является естественной основой для интеграции сервисов через события.

Ответ 18+ 🔞

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

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

API Gateway — это, блядь, главный проходной двор или секретарша-стерва. Все запросы извне идут сначала к нему. Он проверяет пропуск (аутентификация), считает, сколько раз ты уже приходил (rate limiting), и решает, в какую именно конторку тебя направить. Иногда ещё и бумажки с разных столов сам собирает в один пакет, чтобы клиенту не бегать. Я такие шлюзы и на Kong настраивал, и сам на Go писал — чтобы точно под свои приколы заточить.

Service Discovery — а это, ёпта, доска объявлений в холле. Сервис, когда просыпается, пишет: «Я, Василий, бухгалтерия, нахожусь в кабинете 301». Другой сервис, которому надо к бухгалтерии, не тыкается в старый IP-адрес, а сначала смотрит на эту доску (Consul или etcd), узнаёт актуальный адрес Василия и уже тогда идёт. Иначе, если Василий переедет, все ходы к нему будут в пустоту, пиздец.

Circuit Breaker (Предохранитель) — вот это, сука, критически важная вещь. Представь, ты звонишь в соседний сервис, а он лежит. Ты звонишь ещё раз, и ещё. Твои потоки висят, ресурсы кончаются, и ты сам скоро рухнешь. Чтобы этого не было, ставишь «предохранитель». После нескольких неудачных вызовов он говорит: «Всё, хуй с ним, не звони больше туда». И следующие вызовы мгновенно отбиваются ошибкой, без ожидания. Даёт тому сервису время отдышаться. Делал такое через Resilience4j — вещь, ядрёна вошь, жить без неё страшно.

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

CQRS — тут идея простая, но мозг набекрень ставит. Ты разделяешь код для записи и для чтения. Совсем. Как будто у тебя два разных отдела. Один (Command) — принимает заявки на изменение (поставили новый товар). Второй (Query) — оптимизирован только под выдачу данных покупателям (показывает каталог). Часто для чтения делают свою, денормализованную базу, которая обновляется асинхронно. Запросы начинают летать в разы быстрее, но, блядь, согласованность данных теперь не мгновенная, а «в конечном счёте». Подозрение ебать чувствую, когда это объясняю заказчикам.

Event Sourcing — а это вообще, чувак, философия какая-то. Состояние приложения не хранится как «последняя версия правды». Вместо этого хранится лог всех событий, которые когда-либо произошли: «Создан заказ №1», «В заказ №1 добавлена мышка», «Заказ №1 оплачен». Чтобы получить текущее состояние заказа, нужно проиграть все его события с начала. Плюсов куча: полный аудит, можно «отмотать» состояние на любую дату, и это идеальная почва для стыковки сервисов через события. Но сложность, блядь, адская — как отлаживать такую систему, если что-то пошло не так, это отдельная песня.

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