Структура, доп модули, федерация, документация
This commit is contained in:
59
backend/src/Docs/storage_module_documentation.md
Normal file
59
backend/src/Docs/storage_module_documentation.md
Normal file
@@ -0,0 +1,59 @@
|
||||
# Модуль Хранилища (Storage) - Техническая Документация
|
||||
|
||||
## 1. Обзор
|
||||
**Модуль Storage** отвечает за централизованное управление файлами на платформе (аватары, медиа в чатах, вложения в историях). Модуль выступает абстракцией над S3-совместимым объектным хранилищем (в данный момент реализовано через **MinIO**) и интегрируется с криптографическим ядром для обеспечения безопасности файлов.
|
||||
|
||||
Ключевая особенность: модуль реализует концепцию **Zero-Knowledge At-Rest Encryption** — ни один файл не попадает на жесткие диски S3-сервера в открытом виде.
|
||||
|
||||
## 2. Архитектура и Процесс Загрузки
|
||||
|
||||
Сервис [S3FileStorageService](file:///e:/GIT/forkmessager/backend/src/Modules/Storage/Infrastructure/Storage/S3FileStorageService.cs#21-27) (реализация [IFileStorageService](file:///e:/GIT/forkmessager/backend/src/Shared/Knot.Shared.Kernel/Storage/IFileStorageService.cs#6-26) из Shared Kernel) прогоняет файлы через строго определенный пайплайн:
|
||||
|
||||
### 1. Временное буферизирование
|
||||
Поскольку поток загрузки (HTTP Request Stream) зачастую нельзя читать дважды (отсутствует `Seek`), файл сначала сохраняется во временную директорию ОС.
|
||||
|
||||
### 2. Абсолютная дедупликация (SHA-256)
|
||||
Модуль вычисляет криптографический `SHA-256` хэш от содержимого загруженного файла.
|
||||
Именно этот хэш (вместе с расширением) становится именем файла (Object Key) в корзине (Bucket) S3.
|
||||
* **Результат:** Если тысяча пользователей перешлет друг другу один и тот же мем (файл), физически в S3 он будет загружен и сохранен **ровно один раз**, колоссально экономя место на серверах.
|
||||
|
||||
### 3. "На лету" Шифрование (E2EE/At-Rest)
|
||||
Далее применяется `IEncryptionService` (обычно AES-256-CBC).
|
||||
На основе временного файла открывается `CryptoStream`, который шифрует байты файла "на лету" во второй временный файл. Случайный Вектор Инициализации (Initalization Vector, `IV`) генерируется сервисом уникально для каждого файла.
|
||||
|
||||
### 4. Загрузка в S3 с Метаданными
|
||||
Зашифрованный бинарник улетает в MinIO. Чувствительная информация сохраняется **совершенно безопасно** в заголовках метаданных объекта (MinIO Object MetaData):
|
||||
* `ContentType`: Исходный MIME-тип (например, `image/png`).
|
||||
* `OriginalFileName`: Закодированное исходное имя файла (Urlescaped).
|
||||
* `IV`: Вектор инициализации (Base64), необходимый для последующей расшифровки. Без секретного мастер-ключа приложения этот IV бесполезен.
|
||||
* `EncryptionAlgorithm`: Маркер алгоритма (`AES-256-CBC`).
|
||||
|
||||
В конце цикла бэкенд зачищает локальные временные файлы.
|
||||
|
||||
## 3. Процесс Скачивания и Кэширование (API)
|
||||
|
||||
Модуль предоставляет минималистичный REST API интерфейс, реализованный через **Carter** ([FilesEndpoints](file:///e:/GIT/forkmessager/backend/src/Modules/Storage/Presentation/Endpoints/FilesEndpoints.cs#11-54)).
|
||||
|
||||
### Эндпоинты
|
||||
| Метод | Маршрут | Параметры | Описание |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `GET` | `/api/files/{id}` | `?download=true` | Отдает расшифрованный файл. Поддерживает `Range` запросы для стриминга видео и музыки. |
|
||||
|
||||
### Механизм In-Memory Caching (Производительность)
|
||||
Расшифровка файлов (особенно видео) в реальном времени и постоянный запрос их из S3 съедает процессорное время и сетевой канал бэкенда.
|
||||
К эндпоинту скачивания подключен `IMemoryCache`:
|
||||
1. При первом запросе файла (например, аватара популярного пользователя), он скачивается из MinIO во временный файл ОС на бэкенде.
|
||||
2. Файл прогоняется через `CryptoStream` (с использованием `IV` из метаданных корзины S3) для дешифровки и выгрузки в `MemoryStream`.
|
||||
3. Байты готового файла, его `ContentType` и исходное имя кэшируются в RAM бэкенда на **30 минут** (Sliding Expiration).
|
||||
4. Все последующие запросы отдают готовые байты прямо из оперативной памяти без сетевого похода в MinIO и без повторной расшифровки.
|
||||
|
||||
### Поддержка Range-запросов
|
||||
API использует метод `Results.File(..., enableRangeProcessing: true)`. Это означает, что плееры в браузере или мобильном клиенте могут запрашивать видео кусками (например, `Range: bytes=1000-2000`), и бэкенд корректно отдаст только нужный чанк (из кэша или после скачивания), что делает модуль пригодным для видео-стриминга прямо из коробки.
|
||||
|
||||
---
|
||||
|
||||
## Итог
|
||||
Модуль представляет собой пуленепробиваемый шлюз для работы с медиа:
|
||||
* Обеспечивает полную конфиденциальность (ни один файл не хранится открытым в корзине облака).
|
||||
* Защищен от дубликатов (переиспользование за счет SHA-256 хэшей).
|
||||
* Высоко оптимизирован для раздачи горячего контента (In-Memory кэширование и поддержка HTTP Range Streaming).
|
||||
Reference in New Issue
Block a user