Диагностика и Нагрузочное тестирование

Обновлено:

Настройка классических TURN серверов часто превращается в работу "вслепую" администратору приходится ставить сторонние пакеты, вручную проверять прохождение UDP пакетов через NAT и гадать, сколько одновременных видеозвонков выдержит виртуальная машина.

В бинарный файл Slyber Turn Server встроены два профессиональных CLI инструмента, которые закрывают все задачи по проверке и профилированию сервера без установки внешних зависимостей:

  • slyber_turn doctor - автоматический сканер конфигурации, сетевых портов, правил NAT и работоспособности TURN-аллокаций.
  • slyber_turn bench (или benchmark) - многопоточный генератор WebRTC подобного медиа трафика с расчетом пропускной способности, потерь пакетов, круговой и односторонней задержки (RTT / One-Way Latency), а также медиа джиттера по стандарту RFC 3550.

1. Инструмент глубокой диагностики

Команда doctor выполняет комплексную проверку узла: от корректности синтаксиса .env и настройки CORS до реального тестового выделения релейного порта из пула.

Запуск диагностики

Для проверки сервера с использованием текущей конфигурации (/opt/slyber_turn/.env) выполните:

Bash
sudo slyber_turn doctor

При необходимости вы можете переопределить любой параметр конфигурации на лету с помощью флагов командной строки:

Bash
sudo slyber_turn doctor -public-ip 203.0.113.50 -udp-port 3478 -realm rtc.example.com

Что проверяет doctor шаг за шагом

Диагностика проходит в 4 последовательных этапа:

Этап 1. Валидация конфигурации и емкости пула портов

Утилита загружает настройки, проверяет длину секретного ключа (TURN_SECRET не менее 16 символов), отсутствие конфликтов между портами UDP, TCP, TLS и HTTP, а затем вычисляет максимальную емкость одновременных релейных сессий по формуле RELAY_MAX_PORT - RELAY_MIN_PORT + 1.

Этап 2. Аудит защиты HTTP API

Проверяется конфигурация безопасности эндпоинта выдачи временных учетных данных /api/turn-credentials:

  • Если список ALLOWED_ORIGINS пуст и при этом не включен строгий режим REQUIRE_SECRET=true, утилита выведет предупреждение [WARN], так как браузерные CORS-запросы будут отклоняться.
  • Если защита настроена корректно, выводится статус [OK] с количеством разрешенных доменов и статусом require_secret.

Этап 3. Внешняя STUN проверка и сверка NAT

Утилита обращается к внешним STUN-серверам (stun.l.google.com:19302, stun.cloudflare.com:3478, stun1.l.google.com:19302) с таймаутом в 3 секунды, измеряет сетевой RTT и узнает реальный внешний IP-адрес, с которого ваш сервер выходит в интернет:

  • Если обнаруженный внешний IP совпадает с настроенным PUBLIC_IP, проверка проходит успешно ([OK]).
  • Если адреса различаются (например, сервер находится за облачным NAT 1:1 или указан неверный IP в .env), выводится предупреждение [WARN] IP mismatch.
Защита от засорения аналитики: Для тестовых подключений doctor и bench используют зарезервированный системный идентификатор пользователя doctor_probe. Ядро сервера и система телеметрии автоматически распознают это имя и не записывают диагностические проверки в счетчики пользовательских подключений, список активных сессий и журнал событий events.jsonl. Вы можете запускать slyber_turn doctor из cron или систем мониторинга каждую минуту без искажения бизнес-метрик.

Примеры вывода slyber_turn doctor

Успешная проверка работающего сервера:

Code
[INFO] Running slyber_turn doctor diagnostics...
--------------------------------------------------
[OK] Configuration valid (realm: turn.local, relay port pool: 49152-65535, capacity: 16384 sessions)
[OK] HTTP API protection active (origins: 1, require_secret: false)
[OK] STUN check passed in 18ms: PUBLIC_IP (203.0.113.50) matches external IP
[INFO] UDP port 3478 is already in use - switching to running server verification (Live Probe)...
[OK] HTTP API (:8080/healthz) responded normally (200 OK)
[OK] TURN Allocate succeeded in 412µs (allocated relay address: 203.0.113.50:51024)
--------------------------------------------------
[OK] Diagnostics completed successfully. Server is ready.

Успешная проверка перед запуском сервиса (Режим Self-Test):

Plaintext

Code
[INFO] Running slyber_turn doctor diagnostics...
--------------------------------------------------
[OK] Configuration valid (realm: turn.local, relay port pool: 49152-65535, capacity: 16384 sessions)
[OK] HTTP API protection active (origins: 1, require_secret: false)
[OK] STUN check passed in 21ms: PUBLIC_IP (203.0.113.50) matches external IP
[INFO] Ports UDP 3478 / TCP 3478 are free - starting isolated Self-Test...
[OK] TURN Allocate succeeded in 385µs (allocated relay address: 203.0.113.50:49152)
--------------------------------------------------
[OK] Diagnostics completed successfully. Server is ready.


Справочник диагностических сообщений и решение проблем

Сообщение doctorПричина возникновенияКак исправить
[WARN] IP mismatch: configured PUBLIC_IP=..., but external STUN reported ...В .env указан IP адрес, который не совпадает с реальным выходным IP сервера.Установите PUBLIC_IP="auto" в /opt/slyber_turn/.env или укажите правильный публичный IPv4 адрес сервера и перезапустите службу.
[FAIL] UDP port 3478 is free, but TCP port 3478 is already in useНа сервере остановлен TURN, но TCP-порт 3478 (или TLS_PORT 5349) занят другим сторонним процессом.Проверьте, кто занимает порт (sudo ss -tulpn | grep 3478), остановите конфликтующий процесс или смените порт в .env.
[WARN] HTTP API (:8080/healthz) is not respondingTURN-сервер запущен, но HTTP API не отвечает (или запущен с другими флагами/портом).Проверьте статус службы (sudo systemctl status slyber_turn) и настройки HTTP_ENABLED / HTTP_PORT в .env.
[FAIL] TURN Allocate failed on 127.0.0.1:3478Работающий сервер не ответил на запрос выделения порта или отклонил авторизацию.Убедитесь, что порт 3478 не занят чужим STUN/TURN сервером (например, старым coturn), и что вы запускаете doctor с тем же .env, с которым запущен сервис.

2. Нагрузочное тестирование и оценка качества медиа: slyber_turn bench

Команда slyber_turn bench (синоним: slyber_turn benchmark) создает реалистичную нагрузку на TURN сервер, имитируя десятки и сотни одновременных аудио и видеозвонков WebRTC.


Архитектура и алгоритм работы бенчмарка

Тестирование в bench выполняется в 5 фаз:

Определение режима тестирования (mode):

  • self-test: Если флаг -target не указан и порт UDP_PORT свободен, утилита автоматически поднимает внутри себя изолированный TURN-сервер на 127.0.0.1 (с временным разрешением loopback-трафика SetAllowLoopback(true)) и тестирует его.
  • live-local: Если флаг -target не указан, а порт UDP_PORT уже занят работающим сервером slyber_turn, тест автоматически запускается против живого локального сервера (PUBLIC_IP:UDP_PORT).
  • live-remote: Если явно передан флаг -target <host:port>, тест выполняется по сети против указанного удаленного TURN-сервера.

Массовая параллельная аллокация (Allocation Setup):

  • Одновременно в отдельных горутинах запускается N клиентов (-clients), каждый из которых открывает UDP-сокет, проходит HMAC-SHA1 аутентификацию и запрашивает у сервера релейный порт (Allocate).
  • Для каждого клиента фиксируется точное время выделения порта, на основе чего рассчитываются метрики avg, p95 и max.

Разбиение на пары и прогрев каналов (Warmup):

  • Все успешно подключившиеся клиенты объединяются в пары (Клиент А ↔ Клиент Б).
  • Каждая пара обменивается стартовым 24-байтным пакетом через выделенные релейные адреса и выдерживает паузу 80 мс для создания TURN-разрешений (CreatePermission) в обоих направлениях.

Двусторонняя пересылка медиа-пакетов по бинарному протоколу SLYB:

  • В течение заданного времени (-duration) каждый клиент с заданной частотой (-pps) отправляет собеседнику через TURN-релей UDP-пакеты заданного размера (-size).
  • Первые 24 байта каждого пакета содержат специальный заголовок:
  • Байты 0..3: Магическая сигнатура протокола 0x534C5942 (ASCII: "SLYB").
  • Байты 4..7: Флаг направления (0 = PING, 1 = PONG).
  • Байты 8..15: Порядковый номер пакета (seq, uint64).
  • Байты 16..23: Точная метка времени отправки в наносекундах (UnixNano, uint64).
  • Когда Клиент Б получает пакет PING, он вычисляет время прохождения в одну сторону, обновляет сглаженный показатель медиа-джиттера по формуле RFC 3550 ($J = J + (\vert{}D(i-1, i)\vert{} - J)/16$), меняет флаг пакета на PONG (1) и немедленно отправляет его обратно через TURN-релей Клиенту А.
  • Когда Клиент А получает вернувшийся PONG (пакет прошел 4 плеча ретрансляции: A -> TURN -> B -> TURN -> A), он фиксирует доставку и вычисляет полный круговой RTT.

Ожидание пакетов в полете и сбор отчета:

  • По окончании отправки bench ждет до 1500 мс (waitForInFlightPackets), чтобы корректно принять последние пакеты, находящиеся в пути, после чего формирует текстовый или JSON-отчет.

Флаги запуска slyber_turn bench

Специальные флаги бенчмарка:

Флаг CLIПо умолчаниюОписание
-target"" (автовыбор)Адрес целевого TURN сервера в формате host:port. Если не указан, тестируется локальный сервер (live-local или self-test).
-clients10Количество одновременных TURN клиентов (аллокаций). Если указано нечетное число, оно автоматически увеличивается на 1 для формирования полных пар собеседников.
-duration5sДлительность фазы активной генерации медиа-трафика (например, 5s, 30s, 1m).
-size1200Размер каждого UDP пакета в байтах (минимум 24 байта; 1200 байт соответствует типичному размеру WebRTC видео-пакета VP8/VP9/H.264).
-pps50Количество пакетов в секунду, отправляемых каждым клиентом (50 pps = 1 пакет каждые 20 мс, что точно соответствует аудио-потоку Opus в WebRTC).
-jsonfalseВывод итогового отчета в формате JSON (удобно для CI/CD-пайплайнов и автоматического мониторинга).


Дополнительные флаги конфигурации (при удаленном или кастомном тестировании):

Команда bench также поддерживает все базовые флаги конфигурации: -secret (секретный ключ сервера), -realm (доменная область), -udp-port, -tcp-port, -public-ip и -max-kbps (проверка работы шейпера трафика под нагрузкой).


Примеры запуска

1. Быстрый локальный тест по умолчанию (10 клиентов, 5 секунд):

Bash
sudo slyber_turn bench

2. Стресс-тест высокой видео-нагрузки (100 клиентов / 50 пар, 30 секунд, 100 пакетов/сек по 1200 байт):

Bash
sudo slyber_turn bench -clients 100 -duration 30s -size 1200 -pps 100

3. Удаленное тестирование продакшен-сервера с другой машины с выводом в JSON:

Code
slyber_turn bench \
  -target 203.0.113.50:3478 \
  -secret "your-production-turn-secret-key" \
  -realm "turn.yourdomain.com" \
  -clients 20 \
  -duration 10s \
  -json

Разбор результатов тестирования

1. Стандартный текстовый отчет:

Code
[INFO] Starting Slyber Turn benchmark against 127.0.0.1:3478 (mode: live-local, clients: 20, duration: 5s, payload: 1200 B)...
----------------------------------------------------------------------
  Allocation Setup : 20/20 succeeded | avg: 1.42 ms | p95: 2.15 ms | max: 2.40 ms
  Relay Throughput : 19.20 Mbps (2000 packets/sec, 11.44 MB relayed)
  Packet Delivery  : 5000 sent | 5000 recv | 0.00% loss (0 dropped)
  Relay Latency    : ~0.35 ms one-way (4-leg loop RTT avg: 0.70 ms | p50: 0.65 ms | p95: 1.10 ms)
  Media Jitter     : 0.12 ms (RFC 3550)
  Quality Verdict  : [OK] EXCELLENT (Ready for low-latency HD Voice & Video)
----------------------------------------------------------------------

2. JSON-отчет (флаг -json):

При указании флага -json утилита выводит полную структуру метрик (включая дополнительные перцентили rtt_min_ms, rtt_p99_ms, rtt_max_ms и точное число переданных байт bytes_relayed):

JSON
{
  "target": "127.0.0.1:3478",
  "mode": "live-local",
  "clients": 20,
  "duration_sec": 5.0,
  "alloc_success": 20,
  "alloc_failed": 0,
  "alloc_avg_ms": 1.42,
  "alloc_p95_ms": 2.15,
  "alloc_max_ms": 2.4,
  "packets_sent": 5000,
  "packets_received": 5000,
  "packets_lost": 0,
  "packet_loss_percent": 0.0,
  "bytes_relayed": 12000000,
  "throughput_mbps": 19.2,
  "packets_per_sec": 2000.0,
  "rtt_min_ms": 0.41,
  "rtt_avg_ms": 0.7,
  "rtt_p50_ms": 0.65,
  "rtt_p95_ms": 1.1,
  "rtt_p99_ms": 1.48,
  "rtt_max_ms": 1.85,
  "one_way_relay_avg_ms": 0.35,
  "jitter_ms": 0.12,
  "verdict": "[OK] EXCELLENT (Ready for low-latency HD Voice & Video)"
}

Что означает каждая метрика отчета:

  • Allocation Setup (alloc_avg_ms / alloc_p95_ms / alloc_max_ms): Скорость рукопожатия и выделения релейного порта под нагрузкой. Показывает, насколько быстро подключаются новые участники звонка.
  • Relay Throughput (throughput_mbps / packets_per_sec / bytes_relayed): Суммарная скорость прокачки медиа-трафика через TURN-сервер в мегабитах в секунду и пакетах в секунду (учитываются как входящие PING, так и ответные PONG пакеты).
  • Packet Delivery (packet_loss_percent / packets_lost): Процент потерянных UDP-пакетов. Для качественной связи на локальном сервере потери должны быть равны 0.00%.
  • Relay Latency (one_way_relay_avg_ms и rtt_*):
  • 4-leg loop RTT — полное время прохождения пакета туда и обратно через два релейных порта (Клиент А -> TURN -> Клиент Б -> TURN -> Клиент А).
  • one-way (RTT / 2) — чистая задержка ретрансляции в одну сторону (Клиент А -> TURN -> Клиент Б), которую реально ощущают собеседники в разговоре.
  • Media Jitter (jitter_ms): Неравномерность интервалов доставки пакетов, рассчитанная по алгоритму RTP RFC 3550. Низкий джиттер гарантирует отсутствие «роботизированного» голоса и заиканий видео.


Особенность проверки с включенным лимитом скорости (MAX_KBPS_PER_SESSION): Если у вас в .env настроен шейпер трафика (например, MAX_KBPS_PER_SESSION=1000), а вы запустите bench с параметрами, превышающими этот лимит на одного клиента, ограничитель скорости bandwidthLimiter начнет штатно отбрасывать лишние UDP-пакеты. Чтобы протестировать максимальную физическую мощность самого сервера без искусственного шейпинга, передайте флаг -max-kbps 0:

Bash
sudo slyber_turn bench -clients 40 -duration 10s -max-kbps 0