Backend Typescript 1.0.0 Help

Паттерны микросервисной архитектуры

Зачем нужны паттерны

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

Базовые шаблонные сервисы и слои

Edge-слой: API Gateway и BFF

API Gateway — фасад, единая точка входа для внешних клиентов. Выполняет агрегацию, маршрутизацию, политику безопасности, ограничение трафика, кэширование. BFF (Backend For Frontend) — специализированный фасад под конкретный клиент (веб, мобильный), скрывающий сложность внутренних API.

Доменные сервисы (Core Services)

Каждый доменный сервис владеет своей моделью данных и реализует чёткий bounded context. Общение между сервисами — асинхронными событиями или синхронными запросами, в зависимости от критичности и зависимостей.

Сервисы-поддержки (Supporting Services)

  • Auth/Identity — аутентификация, авторизация, управление токенами.

  • Notification — e-mail/SMS/Push, шаблоны, ретраи, дед-леттер.

  • Reporting/Analytics — витрины, материализованные представления.

  • File/Media — загрузка, хранение, CDN-ссылки, вирус-скан.

Паттерны интеграции сервисов

Синхронные запросы/ответы (HTTP/gRPC)

Используются для запросов, требующих мгновенной обратной связи (например, проверка баланса перед оплатой). Подход прост в реализации, но увеличивает связность и риск каскадных таймаутов.

// Gateway -> Orders -> Payments (глубина 2, таймауты короче суммарного SLA) const paymentOk = await withTimeout(() => payments.authorize(orderId), 800);

Асинхронные события (Event-Driven)

Сервисы публикуют факты (события-доменные факты) в шину; подписчики реагируют независимо, что снижает связность и повышает масштабируемость.

Команды (Command) и запросы (Query)

Команда инициирует действие и может быть асинхронной. Запрос читает состояние и обычно синхронен. Разделение упрощает масштабирование и кэширование.

Оркестрация и Хореография: сравнение и применение

Что такое Оркестрация

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

  • Плюсы: прозрачный контроль потока, явные состояния, простая отладка, единые SLA.

  • Минусы: центральная точка координации, потенциальная «бутылочная горлышко», сильнее связь с участниками.

Что такое Хореография

Хореография — распределённая координация: каждый участник подписывается на релевантные события и самостоятельно решает, что делать дальше. Нет единого центра принятия решений.

  • Плюсы: низкая связность, простая эволюция, горизонтальная масштабируемость.

  • Минусы: сложнее прослеживать цепочку, риск непреднамеренных циклов, труднее ввести глобальные правила.

Где какой подход уместен

  • Оркестрация: сложные, регламентированные процессы с явными этапами и компенсациями (оформление кредита, KYC, биллинг). Требуется единая точка контроля статусов.

  • Хореография: событийное расширение вокруг «ядра» (уведомления, аналитика, кэш-проекции, интеграции с партнёрами), где важно низкое сцепление и независимые релизы.

Транзакции, саги и согласованность

Сага как общий паттерн

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

// Оркестрируемая сага (псевдокод) await step("ReserveInventory", () => inventory.reserve(orderId), () => inventory.release(orderId)); await step("AuthorizePayment", () => payments.authorize(orderId), () => payments.refund(orderId)); await step("ConfirmOrder", () => orders.confirm(orderId), () => orders.markFailed(orderId));

Outbox и транзакционная доставка

Outbox — запись события в таблицу outbox в одной транзакции с изменением агрегата, а затем асинхронная публикация из outbox в брокер. Гарантирует «сначала запись, потом публикация» без потерь.

\-- Изменение статуса заказа и запись события в одной транзакции BEGIN; UPDATE orders SET status = 'CONFIRMED' WHERE id = 'o-42'; INSERT INTO outbox(id, topic, payload, created\_at) VALUES ('e-123', 'order.confirmed', '{...}', now()); COMMIT;

CQRS и Event Sourcing

CQRS разделяет модели записи и чтения для масштабирования и целостности. Event Sourcing хранит последовательность событий как источник истины; состояние восстанавливается через «реплей».

Надёжность и устойчивость

  • Circuit Breaker: «размыкает цепь» при ошибках/таймаутах, затем полуоткрытый режим для проб.

  • Bulkhead: изоляция пулов (соединения, очереди) между фичами, чтобы сбой не уронил всё.

  • Повторы с экспоненциальной паузой и джиттером; уважайте идемпотентность.

  • Идемпотентность: повтор одного и того же запроса не меняет итоговое состояние.

  • Таймауты и дедлайны для шагов саги; компенсации и алерты.

  • Dead-Letter Queue для сообщений, не прошедших после N попыток.

// Идемпотентный обработчик сообщения const key = msg.headers["Idempotency-Key"]; if (await store.seen(key)) return; // уже обработано await handle(msg.payload); await store.mark(key);

Версионирование и эволюция контрактов

Контракты должны эволюционировать без «ломающих» изменений: добавляйте поля необязательными, не переименовывайте значения событий, используйте согласованную схему (Avro/JSON Schema/Protobuf) и контрактные тесты потребителей.

Наблюдаемость (Observability)

Три столпа: логирование, метрики, трассировка. Для распределённых процессов обязательно корреляция через traceId/spanId, проброс контекста через шину, спаны на шаги саги и компенсации.

Выбор брокера и модель доставки

Оценивайте семантику доставки (at-least-once, at-most-once, exactly-once как архитектурная цель), требования к порядку, объёмы сообщений, задержки и количество подписчиков.

Примеры применения паттернов по случаям

Оформление заказа (ядро + периферия)

  • Оркестрация для ядра: резерв склада → авторизация платежа → подтверждение заказа → счёт. Явные компенсации при отказе.

  • Хореография для периферии: уведомления, обновление рекомендаций, аналитические проекции, вебхуки партнёрам.

Пополнение баланса (внешние интеграции)

Асинхронные вебхуки от провайдера → хореография реакций (обновить баланс, отправить чек). Оркестратор не нужен, если нет сложных зависимостей.

Возврат средств (компенсационные сценарии)

Оркестрация с явным хранением статусов: REQUESTEDAPPROVEDREFUNDED. Компенсации и SLA на каждом шаге, DLQ для ошибок провайдера.

Чек-лист внедрения

  • Определите границы контекстов и агрегатов. Сервис владеет своей схемой БД.

  • Выберите модель координации: оркестрация (ядро) vs хореография (расширения).

  • Гарантируйте доставку: outbox, идемпотентность, ретраи, DLQ.

  • Добавьте устойчивость: circuit breaker, timeouts, bulkhead, backoff с джиттером.

  • Обеспечьте наблюдаемость: трассировка сквозь все шаги, корреляция по traceId.

  • Планируйте эволюцию контрактов: совместимость, версии, контрактные тесты.

Last modified: 01 October 2025