Архитектура сервиса
Сервер DataHUB (backend) — единое Spring Boot-приложение, но логически разделено на два независимых контура: LK-контур для административного UI и Exchange-контур для шинной части. У каждого контура своя точка входа nginx, свои контроллеры, своя авторизация и своя нагрузочная характеристика. Несмотря на это, оба контура работают с одной БД и одним брокером — общая модель данных не дублируется.
Карта пакетов
Исходный код Сервера DataHUB разделён по верхним пакетам Java следующим образом.
com.datahub
├── backend ← LK-контур: админ-UI, авторизация, нотификации
│ ├── api ← REST-контроллеры LK
│ │ ├── controller admin / auth / bus / health / user
│ │ ├── security JWT, auth-фильтры, verification, util
│ │ └── errors глобальная обработка ошибок
│ ├── config Spring-конфигурация LK-домена
│ ├── db Entity / Repository / Health (JPA)
│ ├── notification email/SMS-пайплайн (rabbitmq receiver/transmitter)
│ └── service сервисы бизнес-логики LK
│
├── exchange ← Exchange-контур: шинная часть
│ ├── cache кеши конфигурации обмена
│ ├── config Spring-конфигурация exchange-домена
│ ├── controller REST-контроллеры обмена
│ ├── error обработка ошибок обмена
│ ├── rabbit работа с RabbitMQ (model, util)
│ ├── service сервисы бизнес-логики обмена
│ └── web web-слой обмена
│
├── dto ← общие DTO, по доменам
│ ├── base
│ ├── client / clientsystem / messageclass / messageroute
│ ├── user (auth / changeemail / changepassword / me)
│ └── validation
│
└── logging ← единый Logger
Граница между com.datahub.backend.* и com.datahub.exchange.* — основная архитектурная инварианта: LK-контур не вызывает напрямую логику exchange-контура и наоборот. Общее — только модель данных в dto и БД.
LK-контур
Обслуживает административный интерфейс DataHUB. Внешний доступ — через nginx на lk.<domain>/api/*, упирающийся в frontend (Next.js) и его REST-вызовы.
Контроллеры
| Пакет | Назначение |
|---|---|
api.controller.admin |
Управление системами, пакетами, маршрутами, пользователями (требует роли администратора) |
api.controller.auth |
Регистрация, вход, 2FA, сброс пароля, refresh токена — см. Безопасность |
api.controller.user |
Профиль текущего пользователя (/me), смена пароля и email |
api.controller.bus |
Просмотр состояния обмена со стороны админа — очереди, подписки, маршруты |
api.controller.health |
Healthcheck-эндпоинты |
Авторизация
api.security — основной модуль авторизации платформы. JWT (access 15m, refresh 7d), pepper-хеширование паролей, верификация email/2FA через OTP. Полная схема — в Безопасности и в Интеграции / Авторизация.
Нотификации
notification.* — асинхронная отправка email и SMS из админ-сценариев (подтверждение почты, 2FA-код, сброс пароля, нотификация о важных событиях).
Архитектурно:
notification.service— публикует событие в RabbitMQ-очередь нотификаций.notification.rabbitmq.transmitter— продюсер (помещает сообщение в очередь).notification.rabbitmq.receiver— консьюмер (читает из очереди и вызывает sender).notification.sender— обёртки над почтовым клиентом и SMS-провайдером.
Внутренняя очередь нужна, чтобы сценарии админ-UI не зависели от состояния SMTP/SMS-провайдера: backend публикует событие — UI получает мгновенный ответ; реальная отправка идёт асинхронно.
Exchange-контур
Обслуживает обмен между подключёнными системами. Внешний доступ — через nginx на exchange.<domain>/*, к которому подключаются клиентские системы напрямую (1С, ERP, мобильные приложения).
Контроллеры и web
exchange.controller и exchange.web — REST-эндпоинты обмена: приём сообщения от отправителя, выдача сообщений получателю, подтверждение обработки, операции с пакетами. Контрактно эти эндпоинты документированы через OpenAPI/Swagger; их состав описан в Интеграции / Транспортный API.
Работа с RabbitMQ
exchange.rabbit — взаимодействие с брокером сообщений. Управляет публикацией сообщений в очереди подписанных получателей, чтением из очередей при выдаче. Подробнее — в Работе с очередями.
Кеш
exchange.cache — Caffeine-кеш над конфигурацией обмена (системы, маршруты, пакеты). Конфигурация обмена меняется относительно редко, а читается на каждом запросе — кеш снимает нагрузку с БД.
При изменении конфигурации через LK-контур backend сбрасывает соответствующий кеш — либо явно (по событию), либо по TTL.
Сервисы и обработка ошибок
exchange.service — бизнес-логика приёма и выдачи сообщений: валидация, маршрутизация, журналирование. exchange.error — отдельная обработка ошибок, специфичных для шинного контура (отличается от админ-ошибок: другие коды, другие сообщения, другая семантика для клиентских систем).
Общие компоненты
DTO (com.datahub.dto.*). Объекты передачи данных, общие для обоих контуров. Сгруппированы по доменам: client, clientsystem, messageclass, messageroute, user/*, base, validation. Один DTO может использоваться и в LK-контроллере (для отображения в админке), и в Exchange-контроллере (для обмена) — но это сознательное решение, не «случайное переиспользование».
База данных (com.datahub.backend.db). Сущности и репозитории JPA. Backend.db живёт под пакетом backend, но используется и из exchange.* — общая модель данных, общий контекст транзакций.
Логирование (com.datahub.logging). Единый Logger, обёрнутый над SLF4J. Используется во всех пакетах для единообразного формата сообщений и контекста (system-id, request-id, message-id, package).
Жизненный цикл запросов
LK-запрос
flowchart LR
B[Браузер] --> N["nginx · lk.<domain>"]
N --> F["Next.js SSR/API"]
F --> LK["backend · LK-controller"]
LK --> P[("PostgreSQL")]
LK -.->|"если требуется"| MQ["RabbitMQ · нотификации"]
Типичная LK-операция: пользователь меняет настройку маршрута → frontend POST'ит в /api/admin/... → LK-контроллер валидирует JWT → сохраняет в PostgreSQL → сбрасывает соответствующий кеш Exchange-контура → возвращает результат.
Exchange-запрос
flowchart LR
IS["Клиентская ИС"] --> N["nginx · exchange.<domain>"]
N --> EX["backend · Exchange-controller"]
EX --> C["Caffeine · кеш маршрутов"]
C -.->|"cache miss"| P[("PostgreSQL")]
EX --> MQ["RabbitMQ · публикация / чтение"]
Типичная Exchange-операция: ИС-отправитель POST'ит сообщение → Exchange-контроллер валидирует авторизацию → читает маршруты из кеша → публикует сообщение в RabbitMQ-очереди подписанных получателей → возвращает подтверждение приёма. В БД при этом ничего не пишется — централизованного «лога доставки сообщений» нет.
Healthcheck
Backend публикует:
/api/actuator/health— встроенный Spring Actuator: liveness, readiness, состояние БД, RMQ, кешей./healthz— упрощённый healthcheck для nginx и docker.
Подробнее — в Развертывание / Мониторинг и логи.
Почему монолит, а не микросервисы
Разделение LK ↔ Exchange сделано на уровне пакетов и контроллеров, но не на уровне отдельных деплоев. Это сознательный выбор:
- Общая БД и общая модель данных — раздробить их между двумя сервисами означало бы либо разделить транзакции (сложно для конфигурации), либо ввести inter-service-вызовы (дополнительная нагрузка и точки отказа).
- LK-контур обычно недогружен (десятки запросов в секунду от админов), Exchange — сильно нагружен; в монолите общие ресурсы (JPA-pool, кеш) шарятся естественно.
- Один артефакт = более простой релиз и эксплуатация: одно обновление, одна проверка совместимости.
Если в будущем нагрузка Exchange-контура потребует отдельного масштабирования — описанная архитектура позволяет вынести его в отдельный сервис без существенной переработки модели. См. Масштабирование.
Что дальше
- Работа с очередями — детали Exchange-контура.
- Безопасность — авторизация в LK-контуре.
- Потоки обмена — путь сообщения через оба контура.
- Развертывание / Сервер DataHUB — операционный взгляд: env, секреты, профили, healthcheck.