Перейти к содержанию

Общая схема платформы

Платформа DataHUB состоит из двух неотъемлемых частей: серверной и клиентской.

Серверная часть — набор независимых Docker-сервисов, объединённых в общую сеть dh_network. Она принимает сообщения, маршрутизирует их через RabbitMQ и предоставляет административный интерфейс. У серверной части две внешне видимых поверхности — административная (Личный кабинет) и обменная (Exchange API), — опубликованные через единый reverse-proxy на nginx.

Клиентская часть — адаптеры DataHUB, которые устанавливаются внутри каждой интегрируемой системы. Адаптер реализует значительную часть логики обмена: формирует и сериализует сообщения, ведёт локальные очереди, выполняет retry при сбоях, обеспечивает идемпотентную обработку входящих данных. Без адаптера система не может участвовать в обмене. Референсная реализация — модуль для 1С; адаптеры для других систем реализуются по той же архитектурной модели.

Внешний взгляд

flowchart TD
    Admin["Администратор\n(браузер)"]

    subgraph client["Клиентская сторона платформы"]
        Systems["Клиентские системы\n(1С, ERP, mobile, web)"]
        Adapters["Адаптеры DataHUB\nлокальные очереди · логика обмена · retry"]
        Systems <--> Adapters
    end

    subgraph server["Серверная сторона платформы"]
        Nginx["nginx"]
        Frontend["frontend · Next.js"]
        LkApi["backend — LK API"]
        ExchangeApi["backend — Exchange API"]
        Postgres["postgres"]
        RabbitMQ["rabbitmq · брокер"]
        RmqMgmt["rabbitmq · Management UI"]
        PgAdmin["pg-admin"]
    end

    Admin -->|"HTTPS :443"| Nginx
    Adapters -->|"HTTPS :443"| Nginx
    Nginx -->|"HTTP :3000"| Frontend
    Nginx -->|"HTTP :80"| ExchangeApi
    Nginx -->|"HTTP :15672"| RmqMgmt
    Nginx -->|"HTTP :80"| PgAdmin
    Frontend -->|"HTTP :80"| LkApi
    LkApi -->|"JPA :5432"| Postgres
    ExchangeApi -->|"JPA :5432"| Postgres
    ExchangeApi -->|"AMQP :5672"| RabbitMQ
    RmqMgmt -. внутри контейнера .-> RabbitMQ
    PgAdmin -->|":5432"| Postgres

Снаружи всегда видны только два HTTPS-узла на 443 порту: lk.<domain> и exchange.<domain>. Всё остальное либо публикуется на отдельных портах с ограниченным доступом (pgAdmin на 15432, RabbitMQ Management на 15672), либо вообще не выходит за пределы Docker-сети.

Сервисы платформы

Платформа состоит из независимых блоков, каждый — отдельный docker-compose.yml в /etc/datahub/<block>/. Связь между блоками — через общую сеть dh_network.

Блок Назначение Внешний доступ
devops-core Управляет сетью dh_network, должен стартовать первым нет
nginx Reverse-proxy, единая точка входа извне 443 (HTTPS), 15432, 15672
frontend Next.js — административный UI (LK) через nginx → lk.<domain>
backend Spring Boot — Сервер DataHUB: REST API, авторизация, маршрутизация через nginx → lk.<domain>/api и exchange.<domain>
postgres PostgreSQL — конфигурация обмена (системы, пакеты, маршруты), пользователи LK только через pg-admin (опционально)
flyway Применяет миграции схемы БД, отрабатывает один раз нет
rabbitmq Брокер сообщений — очереди обмена Management UI через nginx → 15672
pg-admin pgAdmin для администрирования PostgreSQL через nginx → 15432

Подробное описание каждого блока — в Развертывание / Архитектура развертывания. Здесь — только их роль в общей схеме.

Опциональные блоки: firewall (сетевые правила), vpn (узел для удалённого администрирования). В обмене не участвуют.

Адаптеры DataHUB

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

  • Локальные очереди. Адаптер ведёт собственные очереди исходящих и входящих сообщений внутри системы — это обеспечивает работу в условиях нестабильного соединения с сервером.
  • Сериализация и формирование пакетов. Адаптер преобразует объекты системы в стандартный конверт DataHUB и обратно.
  • Управление токенами. Адаптер самостоятельно обновляет access/refresh токены и обрабатывает ошибки авторизации.
  • Retry и идемпотентность. Адаптер повторяет попытки при сбоях и гарантирует, что повторная доставка одного сообщения не приводит к дублированию данных.
  • Идентификация объектов. Адаптер ведёт таблицу соответствия идентификаторов между системами.

Взаимодействие адаптера с сервером — исключительно через Exchange API по HTTPS. Адаптер опрашивает шину (poll или long-polling) и отправляет подтверждения обработки (ACK).

Референсная реализация — модуль для 1С. Адаптеры для других платформ строятся по той же архитектурной модели, описанной в разделе Модули / Общая методология.

Две поверхности Сервера DataHUB

Backend (backend) физически один сервис, но логически он делится на два независимых контура:

LK-контур (com.datahub.backend.*). Обслуживает административный UI: аутентификация, управление пользователями, настройка систем, маршрутов, мониторинг. Запросы приходят на lk.<domain>/api/* от Next.js.

Exchange-контур (com.datahub.exchange.*). Обслуживает обмен — приём сообщений от систем-отправителей, выдача сообщений системам-получателям, управление очередями. Запросы приходят на exchange.<domain>/* напрямую от клиентских систем (1С, ERP, мобильные приложения).

Это разделение — внутри одного Spring Boot-приложения, но с разными контроллерами, разной авторизацией, разными rate-limit'ами. Подробнее — в Архитектуре сервиса.

Поток данных при обмене

При типовом обмене сообщение проходит следующий путь:

  1. Клиентская система-отправитель шлёт POST на exchange.<domain>/... с сообщением.
  2. nginx терминирует TLS и проксирует запрос в backend по внутренней сети.
  3. Backend (Exchange-контур) валидирует авторизацию (см. Безопасность), проверяет права и маршруты по конфигурации в postgres.
  4. Backend публикует сообщение в rabbitmq — в очереди подписанных получателей.
  5. Возвращает клиенту-отправителю подтверждение приёма.

После того как получатель подтверждает обработку, сообщение удаляется из очереди RabbitMQ. Шина его дальше не хранит — содержимое продолжает жить в системе-получателе.

Клиент-получатель в это время может:

  • Опросить exchange.<domain>/... за новыми сообщениями (poll) — backend прочитает их из своей очереди в rabbitmq и отдаст в ответе.
  • Поддерживать постоянное соединение (long-polling) — backend выдаст сообщение, как только оно появится в очереди.

Подробнее путь сообщения — в Потоках обмена.

Поток данных при администрировании

Параллельно с обменом работает административный поток через LK:

  1. Администратор открывает lk.<domain> в браузере.
  2. nginx отдаёт SPA на Next.js (frontend), терминирует TLS.
  3. Frontend выполняет авторизацию через lk.<domain>/api/auth/* (LK-контур backend).
  4. После авторизации — UI работает с REST API LK-контура: списки систем, маршрутов, пользователей, мониторинг очередей.
  5. Все изменения конфигурации — LK-контур пишет в postgres.

Синхронизацию топологии RabbitMQ с конфигурацией в БД выполняет Exchange-контур: он периодически читает актуальные маршруты и очереди из postgres и подкручивает топологию брокера. LK API в RabbitMQ напрямую не обращается.

Что хранится где

Данные Где хранятся Зачем именно там
Конфигурация обмена (системы, пакеты, маршруты) PostgreSQL Транзакционность, JPA, schema-versioned через Flyway
Пользователи LK, роли, парольная политика PostgreSQL Часть админ-домена
Сообщения в полёте (in-flight, до подтверждения) RabbitMQ Брокер по своему назначению — буфер для очередей
Секреты Сервера (pepper, JWT-ключи, service token) Файловая система: /etc/datahub/backend/certs/ Локальная безопасность, не попадают в БД
Конфигурация блоков (.env, docker-compose.yml) Файловая система: /etc/datahub/<block>/ Хост-управление, не зависит от состояния контейнеров
Бинарные вложения Внешнее S3-совместимое хранилище Разгрузка основного транспорта, см. Файловое хранилище

Платформа не хранит бизнес-данные участников обмена и не сохраняет сообщения после их доставки. После подтверждения получателем сообщение удаляется из очереди RabbitMQ — содержимое дальше существует только в системе-получателе. В базе шины остаются только метаданные обмена (системы, пакеты, маршруты, права) и пользователи LK. Централизованный трекинг прохождения сообщений на стороне шины запланирован, но пока в разработке; на текущий момент статус виден на стороне клиентского модуля.

Что дальше