Gemaakt door AIVerbeterd door mensen
Riqli · levende documenten · continu bijgewerkt
Waar AI-kennis menselijke praktijk ontmoet.
Delen met vrienden

Microservices - паттерны и практика построения микросервисов. Hard skill. (Микросервисы. Microservices architecture. Паттерны микросервисов. Api gateway для микросервисов. Tutorial. Practice. Standard.)
1. Введение в микросервисы: когда и зачем
Микросервисная архитектура не является серебряной пулей, и ее выбор должен быть осознанным. Монолит проще в разработке на старте, но с ростом бизнеса он превращается в запутанный клубок зависимостей, где каждая новая фича требует огромных усилий. Мы разберем, когда монолит перестает справляться с нагрузкой и почему микросервисы становятся необходимостью для быстрого масштабирования и независимого развертывания частей системы.
Курс построен на реальном проекте — сайте школы, где мы спроектируем систему с нуля. Наша задача не написать весь бэкенд, а выделить сложные с точки зрения архитектуры части, такие как покупка курсов и саги. Мы пройдем путь от монолита к микросервисам, разберем паттерны и на практике увидим, как асинхронное взаимодействие решает проблемы синхронных вызовов.
2. Декомпозиция: как разбить монолит на сервисы
Ключевой вопрос проектирования — как правильно разделить систему на микросервисы. Мы используем алгоритм из четырех шагов: выделение пользовательских сценариев, поиск бизнес-сущностей, объединение по доменам и минимизация числа сервисов. Ошибка на этом этапе стоит дорого, поэтому мы будем использовать четкую нотацию для описания архитектуры и связи между компонентами.
Важно бояться нано-сервисов, когда одна команда выделяется в отдельное приложение. Признак правильной декомпозиции — слабая связанность и сильная связность внутри домена. Мы изучим паттерны декомпозиции по бизнес-задачам и доменным моделям, чтобы сервисы были автономными и независимо развертываемыми, но при этом сохраняли целостность бизнес-логики.
3. Коммуникация и обмен сообщениями
Микросервисы не могут существовать изолированно — им нужно общаться. Синхронные HTTP-запросы создают жесткие связи и проблемы с отказоустойчивостью. Асинхронное взаимодействие через брокеры сообщений, такие как RabbitMQ, обеспечивает слабую связанность. Мы сравним запрос-ответ, уведомления и событийную модель, чтобы понять, когда и какой паттерн использовать.
RabbitMQ — это брокер, который работает через обменники (exchanges) и очереди. Мы разберем типы обменников: direct, topic, fanout и headers. На практике увидим, как с помощью RPC через RabbitMQ реализовать асинхронный запрос-ответ с уникальным идентификатором, а также как настроить вал идацию входящих данных с помощью class-validator, чтобы обеспечить надежность и консистентность системы.
4. Саги: консистентность данных в распределенных системах
Главная проблема микросервисной архитектуры — обеспечение целостности данных при операциях, затрагивающих несколько сервисов. Паттерн Saga (сага) решает эту проблему через последовательность транзакций с компенсирующими действиями. Мы реализуем оркеструемую сагу покупки курса, где один сервис управляет шагами: проверка курса, генерация платежа и обновление статуса, с откатом при ошибке.
На практике мы соединим саги с паттерном State для управления состояниями покупки: старт, процесс оплаты, успех или отмена. Управление состоянием через конечный автомат делает код предсказуемым и читаемым. Мы также обсудим проблемы дублирования сообщений и блокировок, чтобы избежать конфликтов при параллельном выполнении саг в высоконагруженной системе.
5. Тестирование микросервисной архитектуры
Тестирование в мире микросервисов отличается от монолита. Пирамида тестов сдвигается: юнит-тесты проверяют отдельные компоненты, но ключевую роль играют контрактные тесты, которые проверяют взаимодействие сервисов без поднятия всего окружения. Мы напишем тесты для авторизации и саги, используя моки для внешних сервисов и тестовые модули NestJS, чтобы имитировать ответы RabbitMQ и базы данных.
Мы научимся писать интеграционные тесты, которые проверяют работу сервиса вместе с базой данных, и E2E-тесты, которые прогоняют полный сценарий пользователя через API. Автоматизация тестирования на каждом этапе CI/CD позволяет быстро обнаруживать регрессии и уверенно выкатывать изменения, что критично для поддержания высокого качества в распределенной системе.
6. API Gateway и стратегии получения данных
Вместо того чтобы клиенты обращались к каждому микросервису напрямую, мы используем API Gateway как единую точку входа. Он агрегирует данные из разных сервисов, обеспечивает авторизацию и снижает нагрузку на клиента. Однако важно не превращать Gateway в монолит, наполняя его бизнес-логикой — его задача маршрутизировать и собирать данные, а не решать бизнес-задачи.
Для сложных агрегаций мы применяем паттерн CQRS (Command Query Responsibility Segregation), разделяя команды (изменение данных) и запросы (чтение). Запросы идут в отдельные read-модели (вьюхи), которые обновляются через доменные события. Это позволяет оптимизировать чтение и избежать тяжелых джойнов на лету, обеспечивая высокую производительность даже при сложных выборках из разных доменов.
7. Мониторинг, логирование и выкладка
В распределенной системе критично организовать централизованное логирование и трассировку запросов. Каждый запрос должен проходить через все сервисы с уникальным идентификатором (correlation ID), чтобы можно было восстановить полную цепочку вызовов при ошибке. Стек ELK или Grafana + Loki позволяет собирать и анализировать логи, метрики и трейсы в одном месте.
Выкладка микросервисов в продакшен требует оркестрации, например, с помощью Kubernetes. Контейнеризация (Docker) обеспечивает изоляцию и легкое масштабирование. Важно помнить, что сервисы не должны хранить состояние локально — все данные должны быть во внешних хранилищах (БД, Redis). Мы также рассмотрим стратегии бесшовного деплоя (blue-green) и health checks для автоматического восстановления.
8. Монорепозиторий и инструменты разработки
Для управления несколькими сервисами мы выбираем монорепозиторий, что упрощает обмен контрактами и общими библиотеками. С помощью Nx мы автоматизируем сборку, тестирование и запуск множества приложений. Этот инструмент позволяет легко создавать новые сервисы, использовать общие интерфейсы и обеспечивать консистентность версий зависимостей во всем проекте.
Мы используем NestJS как основной фреймворк благодаря его модульной архитектуре и встроенной поддержке Dependency Injection. NestJS идеально подходит для микросервисов: он позволяет легко переключаться между транспортами (HTTP, RabbitMQ) и тестировать компоненты изолированно. В курсе мы создадим контракты взаимодействия как отдельную библиотеку, чтобы все сервисы работали с единым источником истины.
9. Периодические задачи и кроны
Периодические задачи (например, проверка статуса платежа) в микросервисной архитектуре требуют особого подхода. Если запустить cron в каждом экземпляре сервиса, задачи будут конфликтовать. Решение — выделить один сервис (или API Gateway) как источник задач, который отправляет команды в очередь RabbitMQ, а потребители выполняют работу, распределяя нагрузку между собой.
На практике мы реализуем такой механизм с помощью декораторов @Cron() в NestJS внутри API Gateway. Каждые 5 минут сервис отправляет сообщение в очередь, а все инстансы аккаунт-сервиса, подписанные на эту очередь, обрабатывают задачи по очереди. Это гарантирует, что каждая задача будет выполнена ровно один раз, а нагрузка распределена равномерно.
10. Миграция с монолита на микросервисы
Переход от монолита к микросервисам — это процесс, а не разовое действие. Начинать нужно с выделения проблемных мест, таких как интеграции с внешними API или высоконагруженные модули. Мы используем паттерн Strangler Fig: постепенно заменяем части монолита, прокладывая фасад между старым и новым кодом, что позволяет бизнесу продолжать работать без простоев.
Пошаговый план включает: определение кандидата на выделение, описание контрактов с обратной совместимостью, разработку нового сервиса с тестами и интеграцию через прокси-слой. В итоге мы получаем автономный сервис, который со временем заменяет старый модуль. Переход на микросервисы требует дисциплины, но дает гибкость, масштабируемость и ускоряет разработку для больших команд.
Questions and answers
Какая архитектура проще в разработке на старте, но с ростом бизнеса превращается в запутанный клубок зависимостей?
Монолит
Монолит действительно проще разрабатывать на начальном этапе, но по мере роста бизнеса он становится сложным для поддержки и масштабирования, так как каждая новая функция требует огромных усилий из-за тесной связанности компонентов.
Микросервисная архитектура
Серверлесс
Какая главная проблема микросервисной архитектуры, которую решает паттерн Saga?
Обеспечение целостности данных при операциях, затрагивающих несколько сервисов
Паттерн Saga решает проблему обеспечения целостности данных в распределенной системе, используя последовательность транзакций с компенсирующими действиями для отката при ошибке.
Высокая задержка сети
Сложность развертывания
Какой паттерн используется для разделения команд на изменение данных и запросов на чтение, чтобы оптимизировать производительность?
CQRS (Command Query Responsibility Segregation)
Паттерн CQRS разделяет команды (изменение данных) и запросы (чтение), направляя запросы в отдельные read-модели, которые обновляются через доменные события, что позволяет избегать тяжелых джойнов на лету.
API Gateway
Strangler Fig
Какой инструмент используется в курсе для управления монорепозиторием и автоматизации сборки множества приложений?
Nx
Nx автоматизирует сборку, тестирование и запуск множества приложений в монорепозитории, упрощая создание новых сервисов и использование общих интерфейсов, а также обеспечивает консистентность версий зависимостей.
Docker