Программная архитектура
Монолит
Монолитное приложение(монолит) представляет собой приложение, доставляемое через единое развертывание.
Таким является приложение, доставленное в виде одной WAR или приложение Node с одной точкой входа.
Содержит: UI слой, сервис слой, слой работы с БД и тд.
Multitier
Разделение монолита на несколько частей. Отличие от микросервисов - каждый микросервис может иметь все
слои в себе. Это значит микросервис - маленький монолит.
Обычно разделяется на:
- Presentation layer(Front-end)
- Logic layer(Back-end)
- Data layer(Database administrators)
Распределённые системы
Распределённые системы — это общая концепция, в которой вычисления распределены между несколькими узлами
(компьютерами, серверами, сервисами), работающими вместе для достижения общей цели.
Примеры распределенных систем на java
- Microservice(Микросервисы) - Стек: Spring Boot,
Spring Cloud, Docker, Kubernetes. Стек: Spring Boot, Spring Cloud, Docker, Kubernetes.
- Распределённые вычисления (Big Data, Machine Learning) - Стек: Apache Hadoop, Apache Spark. Пример:
Аналитическая система для обработки больших данных.
- Распределённые базы данных - Стек: Apache Cassandra, Apache Ignite, Redis Cluster. Пример: Глобально
распределённая база данных для социальной сети.
- Распределённые системы на основе акторов - Стек: Akka, Java, Scala. Пример: Чат-приложение с обработкой
сообщений в реальном времени, где каждый пользователь представлен актором.
- Peer-to-Peer (P2P) системы - Стек: JXTA, WebRTC, Netty. Пример: Торрент-клиент или децентрализованное
приложение для обмена файлами.
Виды процессов разработки:
- TDD(Test-driven development)
- DDT(Data-driven testing)
- BDD(Behavior-driven development)
- DDD(Domain-Driven Design)
Event-Driven Architecture (EDA)
Event-Driven Architecture - это архитектурный стиль, основанный на идее обработки событий как основного
способа взаимодействия между компонентами системы. В такой архитектуре приложения реагируют на события,
которые могут быть как внутренними (например, изменение состояния системы), так и внешними (например,
действия пользователя или события, происходящие в других системах).
Основные принципы
- Производители событий генерируют события, которые могут быть асинхронными и происходить в любой момент времени.
- Потребители событий реагируют на эти события, принимая меры или изменяя свое состояние в ответ.
- Обмен событиями может происходить через системы обмена сообщениями, такие как Kafka, RabbitMQ или AWS SNS.
- Асинхронность и декуплинг между компонентами — компоненты не зависят друг от друга напрямую, а
взаимодействуют через события.
- Масштабируемость — благодаря асинхронности система может легче масштабироваться и выдерживать нагрузку.
Domain-Driven Design (DDD)
Domain-Driven Design (Проектирование, ориентированное на предметную область) — это подход к проектированию
программных систем, который ставит в центр внимания бизнес-логику (предметную область) и требует тесного
сотрудничества между разработчиками и экспертами в предметной области. В DDD выделяются такие важные
концепции, как ограниченные контексты, агрегаты, сущности и события домена.
Основные принципы
- Domain Model - центрирование на предметной области. Вся разработка фокусируется на точном моделировании
и понимании бизнес-процессов. Она не просто структура данных, а объединение данных и логики (например,
классы с методами, а не просто DTO).
- Ubiquitous Language - Вся команда (разработчики, аналитики, бизнес) использует единый язык, основанный
на бизнес-терминах. Этот язык отражается в коде — имена классов, методов и т.п.
- Bounded Contexts - Большой бизнес-домен делится на поддомены, каждый из которых реализуется в своем
ограниченном контексте. Например, "Платежи", "Пользователи", "Отчеты" — это могут быть отдельные модули
или микросервисы.
- Entities и Value Objects. Entity (Сущность) — объект с уникальным идентификатором, который сохраняет
свою личность во времени (например, User, Order). Value Object (Объект-значение) — определяется только
своим содержимым (например, Money, Address).
- Aggregates и Aggregate Root. Aggregate — группа связанных сущностей и объектов-значений, объединённых
вокруг одной главной сущности (Aggregate Root). Извне доступ только через корень (например, Order с
OrderLines).
- Domain Events - cобытия, которые описывают что-то важное, что произошло в домене (например,
OrderPlaced, UserRegistered).
Когда применять:
- Сложная предметная область (например, финансы, логистика, страхование).
- Необходимость совместной работы между технарями и бизнесом.
- Проект долгоживущий и будет развиваться.
Не подходит если:
- Проект простой (CRUD-приложение).
- Жесткие сроки и маленькая команда.
- Нет тесного взаимодействия с бизнесом.
Correlation ID
Correlation ID - уникальный идентификатор, который используется для отслеживания запросов в распределённых
системах и микросервисах. Он помогает связывать связанные запросы и упрощает диагностику, логирование
и мониторинг.
Зачем нужно
- Трассировка запросов. В микросервисной архитектуре один пользовательский запрос может порождать
множество внутренних вызовов. Correlation ID позволяет связать их в единую цепочку.
- Упрощение логирования и отладки. Если в логах у каждого запроса есть свой Correlation ID, легче
проследить, как он обрабатывался, и найти возможные ошибки.
- Мониторинг и метрики. Позволяет анализировать производительность и выявлять узкие места в обработке
запросов.
- Диагностика распределённых систем. В распределённых системах запрос может проходить через разные
сервисы. Correlation ID помогает видеть полную картину обработки запроса.
Как работает
Генерация
Correlation ID создаётся на входе в систему (например, при запросе от клиента).
Если запрос приходит с уже существующим Correlation ID (например, от другого микросервиса), он сохраняется.
Передача
Correlation ID передаётся через HTTP-заголовки (например, X-Correlation-ID).
Может использоваться в логах каждого сервиса.
Использование в логах
Логи всех сервисов включают Correlation ID, что упрощает анализ.
Пример использования:
- Отправляем запрос в веб-приложение.
- API-шлюз создаёт Correlation ID и передаёт его дальше.
- Backend получает этот ID и использует его в логах.
- Backend вызывает другие микросервисы, передавая тот же ID.
- Все сервисы логируют свои действия с этим ID.
- В случае ошибки или долгого запроса можно легко проследить, где возникла проблема.