Files
inmake 36a7f79c86 Enhance process management and application launch features in session server
- Added support for launching applications without a graphical window using `-NOSPLASH` and `-NOWINDOW` flags.
- Improved process termination logic with a multi-step approach: soft termination, forced termination, and PowerShell fallback.
- Updated README to reflect new features and enhancements in process management.
2025-12-12 17:43:15 +05:00

413 lines
21 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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. **Проверка времени окончания**: Для активных сессий (`started` или `starting`):
- ⏰ Проверяется время `endAt` - если оно наступило, сессия автоматически переводится в статус `ending`
- **Timezone**: Все время хранится в UTC, сравнение корректно работает независимо от часового пояса сервера
- По умолчанию сессии создаются с временем окончания +30 минут от момента создания
- Автоматическое завершение гарантирует, что сессии не будут работать бесконечно
3. **Запуск приложений**: Для сессий со статусом `starting`:
- ⏰ Проверяется время `startAt` - приложение запускается только если это время уже наступило
- **Timezone**: Все время хранится в UTC, сравнение корректно работает независимо от часового пояса сервера
- Запланированные сессии (с будущим `startAt`) логируются с информацией о времени до запуска
- 🎯 **Централизованное назначение сервера** (для stream-сессий):
- **Main server** автоматически назначает серверы каждые 5 секунд
- Выбирается сервер с максимальной свободной GPU памятью
- Учитываются требования приложения к GPU памяти (`gpuLimitMb`)
- Session-server просто проверяет, что сессия назначена ему
- Запускается соответствующее приложение
- Отслеживается PID процесса
- Статус сессии обновляется на `started` на главном сервере
4. **Остановка приложений**: Для сессий со статусом `ending`:
- Используется `taskkill /pid {PID} /T /F` для завершения всего дерева процессов
- `/T` - завершает указанный процесс и ВСЕ дочерние процессы
- `/F` - принудительное завершение
- Решает проблему с UE5 и другими приложениями, создающими дочерние процессы
- Статус сессии обновляется на `ended` на главном сервере
5. **Автоматическая очистка**: Процессы для неактивных сессий автоматически останавливаются
### 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`)
-**Запуск без графического окна** - использует флаги `-NOSPLASH` и `-NOWINDOW` для UE приложений
- ✅ PID процесса отслеживается и передается на main server
- ✅ Автоматическое обновление статуса при завершении процесса
-**Многоступенчатое завершение процессов**:
1. Мягкое завершение (`taskkill /T`) - отправляет WM_CLOSE сообщение окнам
2. Принудительное завершение (`taskkill /T /F`) - если мягкое не сработало
3. PowerShell завершение - закрывает окна и убивает процесс через PowerShell
- ✅ Решает проблему с 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 (minecraft) истекло, завершение...
[2025-10-06T10:32:00.100Z] ✅ Статус сессии 123e4567-e89b-12d3-a456-426614174000 обновлен на "ending"
```
Остановка сессии:
```
[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