Remove outdated documentation files for companies and migration guide; implement server session management features including server assignment and session status updates; enhance database schema for servers and server sessions with new fields and validation; add auto-assign functionality for unassigned sessions.
This commit is contained in:
@@ -0,0 +1,397 @@
|
||||
# Session Server
|
||||
|
||||
Сессионный сервер для автоматической регистрации на основном API сервере.
|
||||
|
||||
## Описание
|
||||
|
||||
Session Server - это приложение, которое автоматически регистрируется на основном сервере (`stream.graff.tech`) и периодически обновляет свою информацию. Это позволяет основному серверу знать о доступных сессионных серверах для распределения нагрузки.
|
||||
|
||||
## Возможности
|
||||
|
||||
- 🚀 Автоматическая регистрация при запуске
|
||||
- 🔄 Периодическое обновление информации о сервере (по умолчанию каждые 30 секунд после завершения предыдущего запроса)
|
||||
- 🎮 Автоматическое определение и обновление свободной GPU памяти через nvidia-smi (по умолчанию каждую секунду после завершения предыдущего запроса)
|
||||
- 🎯 Автоматическое управление игровыми сессиями
|
||||
- Запуск приложений для сессий со статусом "starting"
|
||||
- Остановка приложений для сессий со статусом "ending"
|
||||
- Отслеживание PID запущенных процессов
|
||||
- Автоматическое обновление статусов сессий на главном сервере
|
||||
- 🌐 Автоматическое определение локального IP адреса
|
||||
- 💻 Автоматическое определение hostname
|
||||
- ⚙️ Гибкая конфигурация через переменные окружения
|
||||
- 🔁 Автоматические повторные попытки при ошибках
|
||||
- 📝 Подробное логирование
|
||||
- ⚡ Защита от наложения запросов для всех операций (рекурсивный вызов через setTimeout)
|
||||
|
||||
## Установка
|
||||
|
||||
```bash
|
||||
# Установка зависимостей
|
||||
bun install
|
||||
```
|
||||
|
||||
## Конфигурация
|
||||
|
||||
Создайте файл `.env` в корне проекта на основе `.env.example`:
|
||||
|
||||
```bash
|
||||
# URL основного API сервера
|
||||
API_URL=http://localhost:3000
|
||||
|
||||
# Тип сервера: stream или local
|
||||
SERVER_TYPE=stream
|
||||
|
||||
# Расположение сервера (ОБЯЗАТЕЛЬНО для stream серверов)
|
||||
# Возможные значения: ru1, uae1
|
||||
SERVER_LOCATION=ru1
|
||||
|
||||
# Уровень сервера (только для stream серверов)
|
||||
# Возможные значения: demo, prod
|
||||
SERVER_TIER=demo
|
||||
|
||||
# ID филиала (ОБЯЗАТЕЛЬНО для local серверов)
|
||||
BRANCH_ID=00000000-0000-0000-0000-000000000000
|
||||
|
||||
# Локальный IP адрес (опционально, определяется автоматически)
|
||||
# LOCAL_IP=192.168.1.100
|
||||
|
||||
# Hostname сервера (опционально, определяется автоматически)
|
||||
# HOSTNAME=my-session-server
|
||||
|
||||
# Интервал регистрации в миллисекундах (по умолчанию 30000 = 30 секунд)
|
||||
REGISTER_INTERVAL_MS=30000
|
||||
|
||||
# Интервал обновления GPU памяти в миллисекундах (по умолчанию 1000 = 1 секунда)
|
||||
GPU_UPDATE_INTERVAL_MS=1000
|
||||
|
||||
# Интервал проверки сессий в миллисекундах (по умолчанию 5000 = 5 секунд)
|
||||
SESSION_CHECK_INTERVAL_MS=5000
|
||||
```
|
||||
|
||||
### Переменные окружения
|
||||
|
||||
| Переменная | Описание | Обязательна | По умолчанию |
|
||||
|------------|----------|-------------|--------------|
|
||||
| `API_URL` | URL основного API сервера | Нет | `http://localhost:3000` |
|
||||
| `SERVER_TYPE` | Тип сервера (`stream` или `local`) | Нет | `stream` |
|
||||
| `SERVER_LOCATION` | Расположение (`ru1`, `uae1`) - **обязательно для `stream`** | Да (для stream) | - |
|
||||
| `SERVER_TIER` | Уровень (`demo`, `prod`) - только для `stream` | Нет | `demo` (для stream) |
|
||||
| `BRANCH_ID` | ID филиала - **обязательно для `local`** | Да (для local) | - |
|
||||
| `LOCAL_IP` | Локальный IP адрес | Нет | Определяется автоматически |
|
||||
| `HOSTNAME` | Hostname сервера | Нет | Определяется автоматически |
|
||||
| `REGISTER_INTERVAL_MS` | Интервал регистрации в мс | Нет | `30000` |
|
||||
| `GPU_UPDATE_INTERVAL_MS` | Интервал обновления GPU памяти в мс | Нет | `1000` |
|
||||
| `SESSION_CHECK_INTERVAL_MS` | Интервал проверки сессий в мс | Нет | `5000` |
|
||||
|
||||
**Примечание:** Свободная память GPU (`gpuFreeMb`) автоматически определяется через `nvidia-smi` при каждой регистрации и обновляется каждую секунду (или согласно `GPU_UPDATE_INTERVAL_MS`) после завершения предыдущего запроса. Это предотвращает наложение запросов. Если `nvidia-smi` недоступен, сервер завершит работу с ошибкой.
|
||||
|
||||
## Управление сессиями
|
||||
|
||||
Session Server автоматически управляет игровыми сессиями на этом сервере:
|
||||
|
||||
### Как это работает
|
||||
|
||||
1. **Проверка сессий**: Каждую секунду (или согласно `SESSION_CHECK_INTERVAL_MS`) сервер запрашивает у основного API список сессий для этого сервера
|
||||
2. **Запуск приложений**: Для сессий со статусом `starting`:
|
||||
- ⏰ Проверяется время `startAt` - приложение запускается только если это время уже наступило
|
||||
- **Timezone**: Все время хранится в UTC, сравнение корректно работает независимо от часового пояса сервера
|
||||
- Запланированные сессии (с будущим `startAt`) логируются с информацией о времени до запуска
|
||||
- 🎯 **Централизованное назначение сервера** (для stream-сессий):
|
||||
- **Main server** автоматически назначает серверы каждые 5 секунд
|
||||
- Выбирается сервер с максимальной свободной GPU памятью
|
||||
- Учитываются требования приложения к GPU памяти (`gpuLimitMb`)
|
||||
- Session-server просто проверяет, что сессия назначена ему
|
||||
- Запускается соответствующее приложение
|
||||
- Отслеживается PID процесса
|
||||
- Статус сессии обновляется на `started` на главном сервере
|
||||
3. **Остановка приложений**: Для сессий со статусом `ending`:
|
||||
- Используется `taskkill /pid {PID} /T /F` для завершения всего дерева процессов
|
||||
- `/T` - завершает указанный процесс и ВСЕ дочерние процессы
|
||||
- `/F` - принудительное завершение
|
||||
- Решает проблему с UE5 и другими приложениями, создающими дочерние процессы
|
||||
- Статус сессии обновляется на `ended` на главном сервере
|
||||
4. **Автоматическая очистка**: Процессы для неактивных сессий автоматически останавливаются
|
||||
|
||||
### API endpoints для управления сессиями
|
||||
|
||||
Session Server взаимодействует с основным сервером через следующие endpoints:
|
||||
|
||||
- `GET /servers/:id/sessions` - получить список сессий для сервера
|
||||
- `PATCH /sessions/:id/status` - обновить статус сессии (публичный endpoint)
|
||||
|
||||
### Запуск приложений
|
||||
|
||||
Session Server автоматически запускает `.exe` приложения по стандартному пути:
|
||||
|
||||
```
|
||||
C:\apps\{appName}\{appName}.exe
|
||||
```
|
||||
|
||||
Где `{appName}` - это значение поля `name` из таблицы `apps`.
|
||||
|
||||
#### Структура директорий
|
||||
|
||||
Все приложения должны быть размещены в следующей структуре:
|
||||
```
|
||||
C:\apps\
|
||||
├── minecraft\
|
||||
│ └── minecraft.exe
|
||||
├── fortnite\
|
||||
│ └── fortnite.exe
|
||||
└── cyberpunk\
|
||||
└── cyberpunk.exe
|
||||
```
|
||||
|
||||
#### Особенности запуска и остановки
|
||||
|
||||
- ✅ Автоматическая проверка существования exe файла
|
||||
- ✅ Рабочая директория устанавливается в папку приложения (`C:\apps\{appName}\`)
|
||||
- ✅ Окно консоли скрывается (`windowsHide: true`)
|
||||
- ✅ PID процесса отслеживается и передается на main server
|
||||
- ✅ Автоматическое обновление статуса при завершении процесса
|
||||
- ✅ **Корректное завершение дочерних процессов** - использует `taskkill /T` для завершения всего дерева процессов
|
||||
- ✅ Решает проблему с UE5 приложениями, которые создают множественные процессы
|
||||
|
||||
#### Логи запуска
|
||||
|
||||
```
|
||||
[2025-10-06T10:00:00.000Z] 🚀 Запуск приложения "minecraft" для сессии abc-123
|
||||
[2025-10-06T10:00:00.050Z] 📂 Путь к приложению: C:\apps\minecraft\minecraft.exe
|
||||
[2025-10-06T10:00:01.000Z] ✅ Приложение запущено с PID 12345
|
||||
[2025-10-06T10:00:01.100Z] ✅ Статус сессии abc-123 обновлен на "started"
|
||||
```
|
||||
|
||||
#### Обработка ошибок
|
||||
|
||||
Если exe файл не найден:
|
||||
```
|
||||
❌ Файл приложения не найден: C:\apps\minecraft\minecraft.exe. Убедитесь, что приложение установлено.
|
||||
```
|
||||
|
||||
### Примеры логов
|
||||
|
||||
Запланированная сессия:
|
||||
```
|
||||
[2025-10-06T10:00:00.000Z] ⏰ Сессия 123e4567-e89b-12d3-a456-426614174000 (minecraft) запланирована через 120 сек
|
||||
```
|
||||
|
||||
Запуск сессии:
|
||||
```
|
||||
[2025-10-06T10:02:00.000Z] 🚀 Запуск приложения "minecraft" для сессии 123e4567-e89b-12d3-a456-426614174000
|
||||
[2025-10-06T10:02:01.000Z] ✅ Приложение запущено с PID 12345
|
||||
[2025-10-06T10:02:01.100Z] ✅ Статус сессии 123e4567-e89b-12d3-a456-426614174000 обновлен на "started"
|
||||
```
|
||||
|
||||
Остановка сессии:
|
||||
```
|
||||
[2025-10-06T10:32:00.000Z] 🛑 Остановка приложения для сессии 123e4567-e89b-12d3-a456-426614174000 (PID: 12345)
|
||||
[2025-10-06T10:32:00.500Z] ✅ Дерево процессов для PID 12345 успешно завершено
|
||||
[2025-10-06T10:32:00.600Z] ✅ Приложение и все дочерние процессы остановлены для сессии 123e4567-e89b-12d3-a456-426614174000
|
||||
[2025-10-06T10:32:00.700Z] ✅ Статус сессии 123e4567-e89b-12d3-a456-426614174000 обновлен на "ended"
|
||||
```
|
||||
|
||||
## Отладка проблем (Troubleshooting)
|
||||
|
||||
Если приложение запускается и сразу завершается с ошибкой, см. подробное руководство по диагностике:
|
||||
- **[TROUBLESHOOTING.md](./TROUBLESHOOTING.md)**
|
||||
|
||||
### Новые возможности логирования
|
||||
|
||||
После обновления вы увидите:
|
||||
- 🔴 **STDERR логи** для диагностики ошибок приложений
|
||||
- 📊 **Счётчик активных процессов** при запуске/завершении
|
||||
- ⚠️ **Детальная информация** о кодах выхода и сигналах
|
||||
|
||||
Пример логов с ошибкой:
|
||||
```
|
||||
[10:51:56.498Z] 🚀 Запуск приложения "ShishimGorka" для сессии abc (активных процессов: 1)
|
||||
[10:51:56.563Z] ✅ Приложение запущено с PID 84112 (всего активных: 2)
|
||||
[10:51:57.500Z] 🔴 STDERR [abc]: Error: Port 8888 is already in use
|
||||
[10:51:57.894Z] 🛑 Приложение для сессии abc завершилось с кодом 1
|
||||
[10:51:57.894Z] ⚠️ Приложение завершилось с ошибкой! Код выхода: 1
|
||||
```
|
||||
|
||||
## Работа с часовыми поясами (Timezone)
|
||||
|
||||
Session Server корректно работает с разными часовыми поясами:
|
||||
|
||||
### Как это работает
|
||||
|
||||
1. **База данных**: PostgreSQL хранит все timestamp с timezone в UTC
|
||||
2. **API**: Основной сервер возвращает время в формате ISO 8601 с timezone (например, `2025-10-06T10:00:00.000Z`)
|
||||
3. **Session Server**: JavaScript автоматически парсит ISO 8601 строки в UTC
|
||||
4. **Сравнение**: Все сравнения времени происходят в UTC, независимо от локального часового пояса сервера
|
||||
|
||||
### Миграция базы данных
|
||||
|
||||
⚠️ **Важно**: Если вы обновляете существующую систему, необходимо выполнить миграцию для добавления timezone в поля `startAt` и `endAt`:
|
||||
|
||||
```bash
|
||||
# Из директории server/
|
||||
psql -d $DATABASE_URL -f timezone_migration.sql
|
||||
```
|
||||
|
||||
См. `server/TIMEZONE_MIGRATION.md` для подробностей.
|
||||
|
||||
### Примеры
|
||||
|
||||
Если сервер в России создаёт сессию на 14:00 по московскому времени (UTC+3):
|
||||
- В БД сохранится: `2025-10-06T11:00:00.000Z` (UTC)
|
||||
- Сервер в ОАЭ (UTC+4) увидит: 15:00 по местному времени
|
||||
- Session Server запустит приложение ровно в 11:00 UTC, независимо от локального времени
|
||||
|
||||
## Запуск
|
||||
|
||||
### Development режим
|
||||
|
||||
```bash
|
||||
bun run dev
|
||||
```
|
||||
|
||||
### Production режим
|
||||
|
||||
```bash
|
||||
# Собрать проект
|
||||
bun run build
|
||||
|
||||
# Запустить собранное приложение
|
||||
bun run start
|
||||
```
|
||||
|
||||
## Примеры использования
|
||||
|
||||
### Stream сервер в России (демо)
|
||||
|
||||
```env
|
||||
API_URL=https://api.stream.graff.tech
|
||||
SERVER_TYPE=stream
|
||||
SERVER_LOCATION=ru1
|
||||
SERVER_TIER=demo
|
||||
REGISTER_INTERVAL_MS=30000
|
||||
```
|
||||
|
||||
### Stream сервер в ОАЭ (продакшн)
|
||||
|
||||
```env
|
||||
API_URL=https://api.stream.graff.tech
|
||||
SERVER_TYPE=stream
|
||||
SERVER_LOCATION=uae1
|
||||
SERVER_TIER=prod
|
||||
REGISTER_INTERVAL_MS=30000
|
||||
```
|
||||
|
||||
### Local сервер для филиала
|
||||
|
||||
```env
|
||||
API_URL=https://api.stream.graff.tech
|
||||
SERVER_TYPE=local
|
||||
BRANCH_ID=123e4567-e89b-12d3-a456-426614174000
|
||||
REGISTER_INTERVAL_MS=60000
|
||||
```
|
||||
|
||||
## Логирование
|
||||
|
||||
Сервер выводит подробную информацию о своей работе:
|
||||
|
||||
```text
|
||||
============================================================
|
||||
🚀 Запуск сессионного сервера
|
||||
============================================================
|
||||
Конфигурация:
|
||||
API URL: http://localhost:3000
|
||||
Hostname: DESKTOP-ABC123
|
||||
Local IP: 192.168.1.100
|
||||
Type: stream
|
||||
GPU Free MB: 8192 (читается из nvidia-smi)
|
||||
Location: ru1
|
||||
Tier: demo
|
||||
Register Interval: 30000ms
|
||||
GPU Update Interval: 1000ms
|
||||
============================================================
|
||||
[2025-10-06T12:00:00.000Z] Регистрация сервера...
|
||||
Данные: {
|
||||
"localIp": "192.168.1.100",
|
||||
"hostname": "DESKTOP-ABC123",
|
||||
"type": "stream",
|
||||
"gpuFreeMb": 8192,
|
||||
"location": "ru1",
|
||||
"tier": "demo"
|
||||
}
|
||||
[2025-10-06T12:00:00.123Z] ✅ Сервер успешно зарегистрирован
|
||||
ID сервера: 123e4567-e89b-12d3-a456-426614174000
|
||||
[2025-10-06T12:00:01.000Z] 🎮 GPU память обновлена: 8150 MB
|
||||
[2025-10-06T12:00:02.000Z] 🎮 GPU память обновлена: 8120 MB
|
||||
[2025-10-06T12:00:03.000Z] 🎮 GPU память обновлена: 8100 MB
|
||||
```
|
||||
|
||||
## Обработка ошибок
|
||||
|
||||
Сервер автоматически обрабатывает ошибки:
|
||||
|
||||
- **Валидация конфигурации**:
|
||||
- Stream-серверы: обязательно должен быть указан `SERVER_LOCATION`
|
||||
- Local-серверы: обязательно должен быть указан `BRANCH_ID`
|
||||
- При отсутствии обязательных полей сервер завершит работу с критической ошибкой
|
||||
- **Сетевые ошибки**: Автоматические повторные попытки (до 3 раз)
|
||||
- **Таймауты**: 10 секунд на запрос
|
||||
- **Коды ошибок**: Повторная отправка при временных ошибках сервера (408, 429, 500, 502, 503, 504)
|
||||
- **Ошибки GPU**: Если `nvidia-smi` недоступен или возвращает некорректные данные, сервер завершит работу с критической ошибкой
|
||||
- **Критические ошибки**: Подробное логирование с завершением работы
|
||||
|
||||
## Архитектура
|
||||
|
||||
```text
|
||||
┌──────────────────────────────────┐
|
||||
│ Session Server │
|
||||
│ │
|
||||
│ Регистрация (рекурсивно): │
|
||||
│ 1. Определение IP │
|
||||
│ 2. Определение hostname │
|
||||
│ 3. Запрос GPU (nvidia-smi) │
|
||||
│ 4. POST /servers/register │
|
||||
│ 5. setTimeout → повтор (30s) │
|
||||
│ │
|
||||
│ Обновление GPU (рекурсивно): │
|
||||
│ 1. Запрос GPU (nvidia-smi) │
|
||||
│ 2. PATCH /servers/:id/gpu │
|
||||
│ 3. setTimeout → повтор (1s) │
|
||||
└──────────┬───────────────────────┘
|
||||
│
|
||||
│ HTTP Requests
|
||||
│
|
||||
▼
|
||||
┌──────────────────────────────────┐
|
||||
│ Main API Server │
|
||||
│ │
|
||||
│ 1. Проверка по hostname │
|
||||
│ 2. Создание/обновление │
|
||||
│ 3. Обновление GPU памяти │
|
||||
│ 4. Возврат данных │
|
||||
└──────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Разработка
|
||||
|
||||
### Структура проекта
|
||||
|
||||
```text
|
||||
session-server/
|
||||
├── src/
|
||||
│ └── index.ts # Основной файл приложения
|
||||
├── dist/ # Собранное приложение
|
||||
├── package.json
|
||||
├── tsconfig.json
|
||||
├── bun.build.ts # Конфигурация сборки
|
||||
└── README.md
|
||||
```
|
||||
|
||||
### Требования
|
||||
|
||||
- Bun >= 1.0
|
||||
- Node.js >= 18 (опционально)
|
||||
- TypeScript >= 5.0
|
||||
- **NVIDIA GPU с установленным `nvidia-smi`** (обязательно)
|
||||
|
||||
## Лицензия
|
||||
|
||||
MIT
|
||||
Reference in New Issue
Block a user