Архитектура
Как веб-приложение, медиасервисы и хранилище взаимодействуют друг с другом при развертывании MeetSpace.
На этой странице
Модель развертывания
Представленное развертывание выполняется на одном хосте Linux с использованием Docker Compose. Процессы приложения представляют собой отдельные контейнеры с частными сетевыми подключениями к общей инфраструктуре. Публичный обратный прокси-сервер завершает HTTPS-соединение и перенаправляет запросы браузера на фронтенд, API и авторизованные загрузки записей.
Веб-фронтенд написан на React и TypeScript, скомпилирован с помощью Vite и обслуживается Nginx. Бэкенд-сервисы написаны на Go. API использует фреймворк Gin, а для передачи медиа в реальном времени - Pion WebRTC. Рабочий файл Compose является эталоном для компоновки сервисов; в конфигурациях для разработки используются дополнительные локальные порты.
Веб-клиенты и клиенты приложений
├─ HTTPS / WSS → Обратный прокси-сервер → Фронтенд и API
│ ├─ PostgreSQL
│ ├─ Redis
│ ├─ RabbitMQ → Сервис записи
│ └─ Частное объектное хранилище
└─ WebRTC ─────→ Медиа-воркер SFU
└─ TURN-ретранслятор при необходимости
SFU → Сервис записи → Объектное хранилище
SFU → Обработчик речи → Настроенный речевой сервис
Фоновый обработчик продукта ↔ PostgreSQL → Настроенные интеграцииСервисы приложения
Медиафайлы в реальном времени не проходят через обычный обработчик запросов API. FFmpeg запускается в модуле записи, отдельно от SFU. Фоновая обработка имеет собственные очереди и ограничения, чтобы в случае сбоя дополнительного провайдера совещание не было намеренно остановлено.
- frontend: обслуживает приложение и общедоступные страницы, а также проксирует запросы к API с тем же источником.
- api: аутентифицирует пользователей, проверяет права доступа, управляет встречами и сообщениями, обслуживает конечные точки REST и соединения в реальном времени, а также планирует работу.
- media-worker: сервис выборочной передачи медиапотоков (SFU). Получает потоки участников и передаёт дорожки другим участникам. Правила допуска и использования устройств задаются управляющими сервисами.
- worker: сервис записи. Он получает команды на запись, захватывает медиафайлы, запускает композитинг и FFmpeg, а также публикует файлы с записями и превью.
- product-worker: выполняет сохраняемые в базе фоновые задания - напоминания, интеграции с почтой и календарём, расшифровку, подготовку итогов и индексирование.
- live-worker: обрабатывает включенное в реальном времени распознавание речи и наблюдения за ходом совещаний для создания субтитров и аналитики.
- migrate: одноразовая задача по миграции базы данных, а не постоянно работающий сервис.
Хранилище и очереди
- В PostgreSQL хранятся учетные записи, права доступа, данные о совещаниях, история переписки, метаданные записей, уведомления, фоновые задания и результаты включенной обработки.
- В объектном хранилище, совместимом с S3, хранятся личные записи, превью, архивы треков и вложения. В классической схеме используется MinIO, а в защищенном установщике - SeaweedFS под совместимым именем сервиса minio. У них разные форматы хранения на диске, поэтому при смене провайдера требуется плановая миграция данных.
- Для захвата и промежуточной записи файлов перед окончательной публикацией используется постоянный буфер.
- Redis хранит временное состояние присутствия, блокировки с ограниченным сроком действия, билеты подключения, ограничения частоты запросов и уведомления в реальном времени. Источником истории переписки остаётся PostgreSQL.
- RabbitMQ доставляет команды управления записью с подтверждениями. Сохраняемая исходящая очередь (outbox) связывает изменения базы данных с публикацией команд.
- Фоновые операции продукта используют сохраняемые задания PostgreSQL с ограниченными повторными попытками и блокировками на время выполнения. Они не зависят от очереди записи RabbitMQ.
Как работает встреча
- Клиент входит в систему или подтверждает получение приглашения на совещание. API проверяет учетную запись, статус совещания и возможность доступа.
- Клиент устанавливает авторизованное соединение в режиме реального времени и обменивается сигналами мультимедиа с сервером. Участники, ожидающие своей очереди, не публикуют медиафайлы в рамках совещания.
- WebRTC подключает клиента к SFU. Coturn обеспечивает ретрансляцию, когда прямое медиасоединение установить невозможно.
- SFU пересылает медиапотоки. Сообщения в чате и элементы управления совещаниями используют API приложения и события в реальном времени, а не встраиваются в видеопоток.
- При запросе на запись API сохраняет запрос и запускает процесс. Модуль записи фиксирует, обрабатывает и загружает артефакты, а затем помечает результат как готовый.
- Если эта функция включена, отдельные фоновые модули создают расшифровки, краткие обзоры, субтитры или аналитические данные, не участвуя в основном процессе пересылки медиапотоков.
Обмен сообщениями и повторное подключение
В личных и групповых чатах используются общие службы обмена сообщениями с проверками доступа на уровне беседы. В чатах совещаний используется тот же базовый механизм обмена сообщениями, но с учетом членства в конкретном совещании. Прямые вызовы используют тот же SFU, но имеют отдельный жизненный цикл для двух участников и не могут принимать приглашения на совещания.
Сервер сохраняет сообщение в PostgreSQL, а затем публикует обновление через Redis и WebSocket-соединения. Уведомления сообщают клиентам о необходимости обновить страницу. Они не являются надежным архивом сообщений. После повторного подключения клиенты снова считывают достоверные данные, поэтому потерянное событие не приводит к удалению сохраненной истории.
Сервер проверяет историю, вложения, роли и изменения в членстве. Сохраненный в личной папке элемент, уведомление или скопированный URL страницы с записью не предоставляют дополнительного доступа.
Границы данных и доступа
В общедоступном развертывании используется протокол HTTPS для веб-трафика и защищенные транспорты WebRTC для передачи медиаданных. Пароли хранятся в виде хешей Argon2id с солью. Для длительных сеансов работы с учетными записями используются защищенные файлы cookie, а авторизация на сервере применяется для каждого защищенного ресурса.
Эти средства защиты при передаче данных не являются сквозным шифрованием: сервер обрабатывает медиаданные для пересылки и записи, а также хранит общий контент. Оператор развертывания несет ответственность за защиту хоста, резервных копий, хранилища и учетных данных.
Дополнительные интеграции могут отправлять адреса электронной почты, данные о расписании, аудиозаписи, расшифровки или фрагменты текста на настроенные провайдеры. Внешняя обработка контролируется настройками функций и конфигурацией провайдера; она должна быть включена в политику организации в отношении обработки данных.
Эксплуатация, производительность и доступность
Сервисы предоставляют внутренние конечные точки для проверки работоспособности, готовности и версии. В классических развертываниях можно включить профиль наблюдаемости с помощью Prometheus и Grafana. Текущая защищенная версия установщика включает Prometheus и не включает Grafana. Метрики и административные конечные точки должны находиться в контролируемых сетях; стандартный общедоступный прокси-сервер блокирует внутренние операционные маршруты.
Стандартный стек включает в себя один хост, базу данных, брокер, объектное хранилище и SFU. Он не обеспечивает автоматическую высокую доступность или динамическую миграцию активного собрания. Замена медиа-воркера может привести к прерыванию звонков и необходимости повторного подключения клиентов.
Производительность зависит от пропускной способности сети, количества видеодорожек, режимов записи, процессора, памяти, скорости диска и лимитов внешних сервисов. Повышение ограничения в настройках само по себе не увеличивает доступную мощность. Проверяйте ожидаемую нагрузку и передачу медиаданных в реальных сетях пользователей.