Перейти к основному содержимому

Модельная архитектура микросервисов

Разработчику Архитектору Аналитику
Теория данных (раздел 3)

Модельная архитектура микросервисов​

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

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


Уровни моделиной архитектуры микросервисов​

Модельная архитектура микросервисов обычно описывается через три основных уровня: уровень сервисов, уровень инфраструктуры и уровень управления. Эти уровни образуют иерархическую структуру, где каждый последующий обеспечивает функциональность предыдущего.


Уровень сервисов​

Уровень сервисов — это ядро микросервисной архитектуры. Он состоит из самих микросервисов, каждый из которых:

  • Реализует одну или несколько тесно связанных бизнес-возможностей.
  • Обладает собственной логикой обработки данных и правилами предметной области.
  • Имеет собственный жизненный цикл — его можно разрабатывать, тестировать, развёртывать и обновлять независимо от других сервисов.
  • Взаимодействует с другими сервисами исключительно через сетевые вызовы, чаще всего посредством HTTP/REST, gRPC или асинхронных сообщений через брокеры.
  • Хранит свои данные в выделенном хранилище, недоступном напрямую другим сервисам.

Каждый микросервис инкапсулирует определённую часть бизнес-логики и данные, необходимые для её выполнения. Это достигается за счёт принципа ограниченного контекста (bounded context), заимствованного из методологии DDD (Domain-Driven Design). Ограниченный контекст определяет границы ответственности сервиса и гарантирует согласованность внутри него.

Сервисы могут быть реализованы на разных языках программирования, использовать разные фреймворки и базы данных. Такая технологическая гетерогенность допустима и даже приветствуется, если она обоснована требованиями конкретной задачи.


Уровень инфраструктуры​

Уровень инфраструктуры обеспечивает среду выполнения для микросервисов. Он включает в себя все технические компоненты, необходимые для запуска, масштабирования, маршрутизации и мониторинга сервисов. Этот уровень скрывает от разработчиков сложность распределённой среды и предоставляет единые механизмы взаимодействия.

Основные элементы уровня инфраструктуры:

  • Платформа оркестрации — система, которая управляет жизненным циклом контейнеров с микросервисами. Наиболее распространённым решением является Kubernetes. Платформа отвечает за запуск экземпляров сервисов, их масштабирование в зависимости от нагрузки, восстановление после сбоев и распределение по узлам кластера.
  • Сетевая инфраструктура — набор компонентов, обеспечивающих маршрутизацию трафика между сервисами и от клиентов к сервисам. Сюда относятся ingress-контроллеры, service mesh (например, Istio или Linkerd), балансировщики нагрузки и DNS-сервисы.
  • Хранилища данных — базы данных, очереди сообщений, кэши и другие системы хранения, используемые микросервисами. Каждый сервис может иметь своё выделенное хранилище, но само хранилище управляется на уровне инфраструктуры.
  • Системы логирования и мониторинга — компоненты, собирающие метрики, логи и трассировки выполнения запросов. Они позволяют отслеживать состояние системы в реальном времени и проводить диагностику проблем.

Уровень инфраструктуры делает микросервисы "невидимыми" для внешнего мира в плане их физического размещения. Сервис может быть перемещён между узлами, перезапущен или заменён новой версией без влияния на логику других компонентов системы.


Уровень управления​

Уровень управления отвечает за процессы, связанные с жизненным циклом микросервисов и всей системы в целом. Он обеспечивает автоматизацию операций, контроль качества, безопасность и соответствие политикам организации.

Ключевые функции уровня управления:

  • CI/CD-конвейеры — автоматизированные процессы сборки, тестирования и развёртывания микросервисов. Каждый сервис имеет свой независимый конвейер, что позволяет командам быстро и безопасно доставлять изменения в продакшен.
  • Репозитории артефактов — хранилища для образов контейнеров, пакетов зависимостей и других артефактов сборки. Они обеспечивают воспроизводимость и отслеживаемость версий.
  • Системы конфигурации — централизованные хранилища параметров конфигурации, которые могут изменяться без пересборки сервисов. Примеры — Consul, etcd, Spring Cloud Config.
  • Политики безопасности и доступа — механизмы управления идентификацией, аутентификацией и авторизацией. Они регулируют, какие сервисы и пользователи имеют право взаимодействовать с конкретными компонентами системы.
  • Инструменты наблюдаемости — платформы для анализа логов, визуализации метрик и построения карт зависимостей между сервисами. Они помогают понимать поведение системы в целом и выявлять узкие места.

Уровень управления превращает микросервисную архитектуру из набора независимых компонентов в управляемую и контролируемую экосистему.


Компоненты модельной архитектуры микросервисов​

Помимо уровней, модельная архитектура микросервисов включает в себя ряд ключевых компонентов, которые обеспечивают её работоспособность и устойчивость.


API Gateway​

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

Функции API Gateway:

  • Аутентификация и авторизация запросов.
  • Ограничение скорости (rate limiting).
  • Преобразование протоколов и форматов данных.
  • Кэширование часто запрашиваемых данных.
  • Логирование и мониторинг трафика.

Использование API Gateway упрощает взаимодействие клиентов с системой и снижает связанность между клиентской частью и внутренней структурой микросервисов.


Service Registry и Discovery​

В динамической среде микросервисы могут появляться и исчезать в любой момент. Service Registry — это централизованный каталог, в котором регистрируются все активные экземпляры сервисов вместе с их сетевыми адресами. Service Discovery — механизм, с помощью которого сервисы находят друг друга в этом каталоге.

Процесс работы:

  1. При запуске микросервис регистрируется в Service Registry.
  2. Перед отправкой запроса к другому сервису он запрашивает его текущий адрес из Service Registry.
  3. После завершения работы сервис удаляется из реестра.

Этот механизм обеспечивает гибкость и отказоустойчивость системы, так как маршрутизация запросов всегда направляется к доступным экземплярам.


Message Broker​

Асинхронное взаимодействие между микросервисами осуществляется через брокер сообщений. Это промежуточная система, которая принимает сообщения от отправителя и доставляет их получателю. Брокер обеспечивает временную изоляцию компонентов и повышает устойчивость системы к временным сбоям.

Преимущества использования Message Broker:

  • Декуплинг производителей и потребителей сообщений.
  • Гарантированная доставка даже при недоступности получателя.
  • Возможность реализации шаблонов обмена — publish-subscribe, point-to-point, dead-letter queues.
  • Поддержка транзакционной целостности в распределённых операциях.

Популярные решения — RabbitMQ, Apache Kafka, NATS, Amazon SQS.


Circuit Breaker​

Circuit Breaker — это паттерн устойчивости, который предотвращает каскадные сбои в системе. Когда один микросервис становится недоступен или начинает отвечать слишком медленно, Circuit Breaker временно блокирует все запросы к нему, возвращая клиенту заглушку или кэшированный результат.

Механизм работы:

  • В нормальном состоянии Circuit Breaker передаёт запросы к целевому сервису.
  • При превышении порога ошибок или задержек он переходит в состояние "разомкнуто".
  • В этом состоянии все запросы сразу же отклоняются без попытки вызова сервиса.
  • Через заданный интервал времени Circuit Breaker переходит в "полуразомкнутое" состояние, пропуская ограниченное количество запросов для проверки доступности сервиса.
  • Если проверка успешна, он возвращается в нормальное состояние.

Этот компонент защищает систему от перегрузки и даёт время на восстановление недоступных сервисов.


Sidecar-контейнеры и Service Mesh​

Sidecar — это вспомогательный контейнер, размещаемый в одном поде с основным микросервисом. Он берёт на себя задачи, не связанные напрямую с бизнес-логикой — шифрование трафика, сбор метрик, управление маршрутами.

Service Mesh объединяет все sidecar-контейнеры в единую сеть, управляемую централизованно. Он предоставляет такие функции, как:

  • Безопасная коммуникация между сервисами (mTLS).
  • Точечное управление трафиком (canary-релизы, A/B-тестирование).
  • Наблюдаемость на уровне сети.
  • Политики отказоустойчивости.

Service Mesh выносит всю инфраструктурную логику из кода микросервисов, позволяя разработчикам сосредоточиться исключительно на бизнес-задачах.


Компоненты модельной архитектуры микросервисов (продолжение)​

Конфигурационные серверы и централизованное управление параметрами​

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

Конфигурационный сервер — это централизованное хранилище параметров, к которому микросервисы обращаются при старте или во время выполнения. Такой подход позволяет:

  • Изменять поведение сервиса без пересборки и повторного развёртывания.
  • Поддерживать разные конфигурации для разных окружений (dev, staging, prod).
  • Версионировать изменения конфигурации и откатывать их при необходимости.
  • Контролировать доступ к чувствительным параметрам через политики безопасности.

Популярные решения включают Spring Cloud Config, Consul, etcd, HashiCorp Vault (для секретов) и AWS Systems Manager Parameter Store. Эти системы интегрируются с платформами оркестрации и CI/CD-конвейерами, обеспечивая единый источник правды для всех параметров системы.


Централизованная система логирования и мониторинга​

В распределённой системе из десятков или сотен микросервисов отладка ошибок и анализ производительности невозможны без единой системы сбора и анализа данных. Логи, метрики и трассировки запросов объединяются в три основных потока наблюдаемости.

  • Логирование — запись событий, происходящих в каждом сервисе. Логи структурируются в формате JSON и отправляются в централизованное хранилище, такое как Elasticsearch, Loki или Splunk. Это позволяет выполнять поиск по всему кластеру, фильтровать события по сервису, уровню важности или пользовательскому ID.
  • Метрики — количественные показатели состояния системы — количество запросов в секунду, время ответа, использование CPU и памяти, частота ошибок. Системы вроде Prometheus собирают эти данные с каждого узла и предоставляют интерфейсы для визуализации через Grafana.
  • Трассировка — отслеживание пути одного запроса через все микросервисы. Каждый запрос получает уникальный идентификатор (trace ID), который передаётся между сервисами. Инструменты вроде Jaeger или Zipkin собирают временные метки каждого этапа обработки и строят карту вызовов, позволяя точно определить узкое место.

Эти компоненты работают совместно, обеспечивая полную прозрачность над поведением системы в реальном времени.


Шаблоны взаимодействия между микросервисами​

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

  • Снхронный вызов через REST/gRPC — наиболее распространённый способ, когда один сервис напрямую вызывает другой и ждёт ответа. Этот подход прост, но создаёт временную зависимость: если целевой сервис недоступен, вызывающий сервис может зависнуть или завершиться с ошибкой.
  • Асинхронное сообщение через брокер — сервис публикует событие, не заботясь о том, кто его получит. Получатели подписываются на нужные типы событий и обрабатывают их независимо. Это снижает связанность и повышает отказоустойчивость.
  • Event Sourcing — вместо хранения текущего состояния объекта сервис сохраняет последовательность событий, которые привели к этому состоянию. Это позволяет восстановить состояние на любой момент времени и легко реализовать аудит изменений.
  • CQRS (Command Query Responsibility Segregation) — разделение операций записи и чтения. Команды (изменения данных) обрабатываются одним набором сервисов, а запросы (чтение) — другим, часто с использованием материализованных представлений для ускорения ответа.

Эти шаблоны не исключают друг друга и часто комбинируются в рамках одной системы.


Управление жизненным циклом и версионирование​

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

  • Независимые CI/CD-конвейеры — каждый сервис проходит сборку, тестирование и развёртывание отдельно. Это позволяет командам выпускать изменения в любое время без координации с другими группами.
  • Семантическое версионирование API — при изменении контракта взаимодействия (например, добавлении нового обязательного поля) выпускается новая версия API. Старые клиенты продолжают работать со старой версией, пока не будут адаптированы.
  • Канареечные релизы и A/B-тестирование — новая версия сервиса запускается параллельно со старой, и часть трафика направляется на неё. Это позволяет проверить стабильность и производительность до полного перехода.
  • Откат и аварийное восстановление — в случае критической ошибки система автоматически переключается на предыдущую рабочую версию, минимизируя время простоя.

Такой подход делает процесс доставки программного обеспечения предсказуемым, безопасным и гибким.


Безопасность на всех уровнях​

Безопасность в микросервисной архитектуре реализуется сквозным образом — от сетевого уровня до бизнес-логики.

  • Аутентификация и авторизация — каждое взаимодействие между сервисами проходит проверку подлинности. Используются токены (JWT, OAuth2), сертификаты или доверенные прокси (например, Istio mTLS).
  • Шифрование трафика — все сетевые вызовы шифруются с помощью TLS, даже внутри внутренней сети. Это предотвращает прослушивание и подмену данных.
  • Политики доступа — определяются правила, какие сервисы могут вызывать другие. Например, сервис оплаты может вызывать только сервис заказов, но не сервис рекомендаций.
  • Управление секретами — пароли, ключи API и другие чувствительные данные хранятся в защищённых хранилищах (Vault, AWS Secrets Manager) и подгружаются в сервисы только во время выполнения.

Безопасность рассматривается не как дополнительный слой, а как неотъемлемая часть архитектуры.


Принципы проектирования модельной архитектуры микросервисов​

Модельная архитектура микросервисов опирается на ряд фундаментальных принципов, которые обеспечивают её жизнеспособность, масштабируемость и долгосрочную поддерживаемость. Эти принципы не являются техническими требованиями, но служат ориентирами при принятии архитектурных решений.


Автономия сервисов​

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

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


Границы ограниченного контекста​

Ограниченный контекст — это концепция из DDD (Domain-Driven Design), которая определяет чёткие границы ответственности для каждого сервиса. Внутри контекста термины, правила и модели имеют однозначное значение. За пределами контекста эти понятия могут трактоваться иначе.

Разделение системы на ограниченные контексты помогает избежать семантической путаницы и дублирования логики. Например, понятие "клиент" в сервисе маркетинга может означать контакт для email-рассылки, а в сервисе продаж — юридическое лицо с договором. Эти две сущности не должны смешиваться, даже если они относятся к одному физическому человеку.

Границы контекстов становятся естественными границами микросервисов. Это делает архитектуру более согласованной с бизнес-реальностью.


Отказоустойчивость по умолчанию​

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

Отказоустойчивость достигается не только за счёт кода, но и за счёт инфраструктуры — автоматическое восстановление экземпляров, перераспределение нагрузки, резервирование хранилищ. Цель — обеспечить, чтобы частичный сбой не приводил к полному останову системы.


Наблюдаемость как обязательное требование​

Если система не наблюдаема, она неуправляема. Каждый микросервис обязан генерировать структурированные логи, предоставлять метрики выполнения и поддерживать сквозную трассировку запросов. Эти данные собираются централизованно и используются для мониторинга, анализа производительности и диагностики инцидентов.

Наблюдаемость встраивается в процесс разработки с самого начала. Команды определяют ключевые показатели эффективности (SLO) и строят дашборды, которые отражают состояние сервиса в реальном времени. Это позволяет оперативно реагировать на отклонения от нормы.


Декларативность и идемпотентность​

Интерфейсы микросервисов стремятся к декларативному стилю — клиент описывает желаемое состояние, а сервис заботится о том, как его достичь. Например, вместо последовательности команд "создать заказ", "добавить товар", "применить скидку" клиент отправляет один объект заказа в целевом состоянии.

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


Эволюционность и обратная совместимость​

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

  • Добавления новых полей без удаления старых.
  • Использования версионирования URL или заголовков.
  • Поддержки нескольких форматов входных данных.
  • Постепенного вывода устаревших функций с предварительным уведомлением.

Эволюционность позволяет системе расти и адаптироваться к меняющимся требованиям без болезненных миграций.