Эта статья продолжает цикл статей о нагрузочных тестах нашего сервера. Мы уже рассмотрели, как собирать метрики, как на основе этих метрик подбирать оборудование и сравнили способы тестирования. Сегодня посмотрим, как ведет себя сервер при работе с микшированием потоков.
Многие продукты, например, чаты, системы видеоконференций или вебинаров, небольшие системы видеонаблюдения, часто работают на основе микшера, поэтому можно считать микширование потоков одним из самых популярных инструментов.
Микширование производится на стороне сервера и значительно нагружает ресурсы CPU и RAM, поэтому возникает вопрос:
Так сколько же все-таки может быть микшеров на сервере?
В теории, нет никакого ограничения, кроме здравого смысла и производительности серверного железа. То есть, и микшеров на сервере может быть сколько угодно, и потоков в один микшер тоже можно добавить сколько угодно.
Давайте убедимся в этом на практике и опытным путем подберем оптимальное число микшеров и потоков.
Немного математики
Начнем тестирование с проверки пропускной способности канала связи между серверами с помощью Iperf. Пропускная способность канала связи между серверами в нашем случае 8.7 Gbps
В этом тестировании мы публикуем потоки с разрешением 720p. Один такой поток занимает примерно 2 Mbps канала. Для того, чтобы качество потока оставалось стабильным, канал не должен быть загружен более чем на 80% . Исходя из измеренной пропускной способности теоретически мы можем опубликовать 4000 потоков 720p без потери качества.
В качестве тестируемого сервера мы используем сервер со следующими техническими характеристиками
Intel(R) Xeon(R) CPU E5-2696 v2 @ 2.50GHz (24 ядра, 48 гипертрейдинговых потоков);
128 GB RAM;
10 Gbps.
При работе микшеров используется транскодинг. Рекомендуется планировать серверные мощности из расчета 2 ядра CPU на 1 микшер т.е. для нашего 48 поточного сервера теоретически можно запустить 24 микшера.
В тестах мы будем использовать видеоролик с разрешением 720р. Подробнее параметры ролика на скриншоте ниже:
Готовим серверы
Для тестирования нам понадобится один установленный и настроенный экземпляр WCS. Предполагаем, что у вас он уже есть. Если нет, то устанавливаем по этой инструкции.
Готовим сервер к тестированию и подключаем к мониторингу Prometheus+Grafana как в этой статье с небольшой разницей:
-
Для большей наглядности разделим графики открытых декодеров и энкодеров. Число декодеров = число потоков в микшерах. Число энкодеров = число микшеров. Метрики для Grafana:
native_resources{instance="demo.flashphoner.com:8081", job="flashphoner", param="native_resources.video_decoders"}
и
native_resources{instance="demo.flashphoner.com:8081", job="flashphoner", param="native_resources.video_encoders"}
-
При первом тестировании мы будем считать не исходящие WebRTC, а входящие RTMP подключения. Метрика для Grafana:
streams_stats{instance="demo.flashphoner.com:8081", job="flashphoner", param="streams_rtmp_in"}
-
В процессе второго тестирования нам пригодится число существующих VOD на WCS сервере. т.к. на момент написания статьи эта информация была доступна только по REST запросу, модифицируем скрипт для получения кастомных метрик.
В скрипт "custom_stats.sh" добавим следующие команды:
curl -X POST -H "Content-Type: application/json" http://localhost:8081/rest-api/vod/find_all > vod.txt vod_stream=$(head -n 1 vod.txt | grep -o "localMediaSessionId" | wc -l) echo "vod-stream-qty=$vod_stream"
Здесь мы с помощью REST запроса получаем информацию о всех VOD потоках на сервере и подсчитываем их количеству по числу открытых медиасессий. Количество VOD потоков выводится на страницу статистики в переменную "vod-stream-qty", откуда ее считывает Prometheus. Пример файла "custom_stats.sh" можно скачать в разделе "Полезные файлы" в конце статьи.
Метрика для Grafana:
custom_stats{instance="demo.flashphoner.com:8081", job="flashphoner", param="vod-stream-qty"}
В разделе "Полезные файлы" вы можете скачать панели для Grafana со всеми нужными для тестирования метриками.
-
Оптимизируем настройки микшера. Как правило, микшер кодирует один видео поток и множество аудио, по два потока на каждого участника плюс один общий аудио поток. Поэтому рекомендуется задавать число процессорных потоков для кодирования аудио больше, чем для кодирования видео.
Многопоточное микширование и количество процессорных потоков для микширования аудио и видео задаются следующими настройками в файле flashphoner.properties (файл настроек flashphoner.properties можно скачать в разделе "Полезные файлы"):
mixer_type=MULTI_THREADED_NATIVE mixer_audio_threads=10 mixer_video_threads=4
-
Включаем или отключаем ZGC. В зависимости от задачи нужно решить, использовать новый Z Garbage Collector или классический CMS. CMS менее требователен к ресурсам сервера, не занимает большой процессорной мощности, но и паузы для его работы могут быть существенными. Мы рекомендуем использовать CMS на средних по мощности серверах и в случаях, когда требуется большое число не-реалтаймовых микшеров. Например, когда микшеры используются для записи потоков.
Для реалтайма и MCU лучше использовать ZGC. Число микшеров в этом случаем может быть меньше, чем в случае использования CMS, но и паузы в работе Garbage Collector будут значительно меньше, что позволит добиться более плавного воспроизведения выходного потока в случаях использования микшера для проведения различных конференций, видеочатов или вебинаров.
Тип используемого Garbage Collector задается в файле wcs-core.properties. Подробнее в документации.
Тест первый: по сети
Если в имени публикуемого RTMP-потока есть символ '#', сервер рассматривает все, что написано после этого символа, как имя микшера, который будет создан автоматически при публикации потока. Для первого тестирования на другом сервере с помощью ffmpeg создаем RTMP-потоки, которые будут ретранслироваться на тестируемый сервер и затем автоматически собраны в микшеры.
Публикацию запускаем при помощи скрипта:
#! /bin/bash
mixer=24
stream=2
for i in `seq 1 $mixer`; do
for j in `seq 1 $stream`; do
ffmpeg -re -i /root/test.mp4 -acodec copy -vcodec copy -g 24 -strict -2 -f flv "rtmp://172.16.40.21:1935/live/test$j#mixer$i" -nostdin -nostats </dev/null >/dev/null 2>&1 &
done
done
где:
mixer - количество создаваемых микшеров;
stream - число потоков в каждом микшере.
Опытным путем подберем максимальное количество микшеров и потоков в них, чтобы качество воспроизведения выходного потока микшера было оптимальным.
Начнем тестирование с 4 микшеров по 15 потоков:
В этом тестировании нагрузка на тестируемый сервер была не большой, Load Average 1 (зеленая линия на графике)15-20 единиц. Деградации потоков не выявлено. Визуально выходной поток микшера проигрывался с приемлемым качеством.
В следующей итерации увеличим число микшеров до 8 при тех же 15 потоках на микшер:
В этом случае сервер не справился с нагрузкой. Load Average 1 (зеленая линия на графике) в пике около 150 единиц. С первых минут теста зафиксирована деградация стримов. В контрольном потоке наблюдаются фризы.
Попробуем уменьшить количество микшеров.
6 микшеров по 15 потоков:
Картина немногим лучше - все признаки того, что сервер не справляется сохранены - высокий Load Average 1 (более 100 единиц) и деградация стримов.
5 микшеров по 15 потоков:
Теперь все в порядке — Load Average 1 менее 40 единиц и нет деградировавших стримов. Контрольный поток тоже проигрывается правильно, без артефактов и фризов:
Как видите, число микшеров для 15 потоков (читай "комнат для конференций") получилось достаточно скромным. Протестируем второй вариант использования микшера — комнаты для видеочата один на один:
Начнем тестирование с 12 микшеров по 2 потока:
Этот тест сервер прошел успешно. Load Average 1 менее 10 пунктов (зеленая линия на графике). Отсутствие деградировавших стримов. Контрольный поток воспроизводился гладко:
Теперь добавим еще 12 микшеров. Как вы помните, выше мы говорили, что из расчета 2 ядра CPU на 1 микшер для нашего 48 поточного сервера 24 микшера это максимальное количество. Тест 24 микшера по 2 потока:
Этот тест не пройден. Сервер не справился с нагрузкой (пик Load Average 1 75 единиц) и наблюдалась деградация стримов.
Итак, искомое максимальное число микшеров для 2 потоков находится где-то между 12 и 24 микшерами. Чтобы минимизировать число тестов используем стратегию, похожую на бинарный поиск.
Тест 18 микшеров по 2 потока:
Тест пройден. Load Average 1 в пике чуть больше 20 пунктов и отсутствие деградировавших стримов. К контрольному потоку тоже замечаний нет:
Тест 21 микшер по 2 потока:
Тест пройден. Пик Load Average 1 составил около 50 пунктов. Деградировавших стримов так же не зафиксировано.
Тест 23 микшера по 2 потока:
Тест не пройден. Регистрируется деградация стримов. Остается проверить последний вариант - 22 микшера по 2 потока:
К сожалению, ближе к завершению теста была зафиксирована деградация 40% стримов, поэтому тест нельзя считать успешным.
Следовательно, максимальное число микшеров по 2 потока на нашем сервере — 21 микшер.
Результаты тестирования микшеров в таблице:
Число микшеров |
Число потоков в каждом микшере |
Результат теста |
---|---|---|
4 |
15 |
Пройден |
5 |
15 |
Пройден |
6 |
15 |
Не пройден |
8 |
15 |
Не пройден |
12 |
2 |
Пройден |
18 |
2 |
Пройден |
21 |
2 |
Пройден |
22 |
2 |
Не пройден |
23 |
2 |
Не пройден |
24 |
2 |
Не пройден |
Тест второй: бессетевой
В этом варианте тестирования мы исключаем из теста сеть. Потоки будем публиковать локально по технологии VOD (Video on Demand). Для захвата используем тот же ролик 720р, что и в предыдущем тесте.
Для работы с VOD добавим следующие настройки в файл flashphoner.properties
vod_live_loop=true
vod_stream_timeout=14400000
где:
vod_live_loop=true - циклический захват потока, после окончания файла захват начинается сначала;
vod_stream_timeout=14400000 - настройка продолжительности публикации VOD потока после отключения подписчиков. Задается в мс, по умолчанию 30 сек, мы указали 4 часа.
Скрипт для запуска тестирования:
#! /bin/bash
contentType="Content-Type:application/json"
mixer=24
stream=2
for i in `seq 1 $mixer`; do
data='{"uri":"mixer://mixer'$i'", "localStreamName":"mixer'$i'", "hasVideo":"true", "hasAudio":"true"}'
curl -X POST -H "$contentType" --data "$data" "http://localhost:8081/rest-api/mixer/startup" -nostdin -nostats </dev/null >/dev/null 2>&1 &
for j in `seq 1 $stream`; do
dataj='{"uri":"vod-live://test.mp4", "localStreamName":"test'$i'-'$j'"}'
datai='{"uri":"mixer://mixer'$i'", "remoteStreamName":"test'$i'-'$j'", "hasVideo":"true", "hasAudio":"true"}'
curl -X POST -H "$contentType" --data "$dataj" "http://localhost:8081/rest-api/vod/startup" -nostdin -nostats </dev/null >/dev/null 2>&1 &
sleep 1s
curl -X POST -H "$contentType" --data "$datai" "http://localhost:8081/rest-api/mixer/add" -nostdin -nostats </dev/null >/dev/null 2>&1 &
done
done
В этом варианте тестирования мы исключили сеть, но часть процессорных ресурсов теперь занята обработкой VOD. Повторим тесты и посмотрим на результаты.
Подбор количества микшеров для 15 потоков.
Начнем с максимума в прошлом тестировании. 5 микшеров по 15 VOD потоков:
Тест пройден. Деградация стримов не зафиксирована. Контрольный поток воспроизведен успешно:
Попробуем увеличить число микшеров. 6 микшеров по 15 VOD потоков:
Как и для RTMP потоков, тест 6 микшеров по 15 потоков не пройден. На графике видно, что присутствует деградация стримов и в контрольном потоке наблюдается подвисание картинки:
Теперь протестируем 24 микшера по 2 VOD потока. Это, как вы помните, максимальное количество микшеров для нашего 48 поточного сервера.
К сожалению, этот тест провалился. Обработка VOD потоков на том же сервере, что и микшеры, нагружает процессор, поэтому такой результат теста вполне ожидаем. Значение Load Average 1 около 80 единиц (зеленая линия на графике) свидетельствует о высокой нагрузке на процессор. Были зарегистрированы деградировавшие стримы. Контрольный поток так же показал фризы:
Проверим 12 микшеров по 2 VOD потока:
Этот тест пройден. Деградации стримов не зафиксировано, контрольный выходной поток случайного микшера воспроизводился без артефактов и фризов:
Значит, искомое максимальное число микшеров по 2 потока находится между 24 и 12.
Тест 18 микшеров по 2 VOD потока:
Тест пройден. Деградации стримов не зафиксировано, контрольный поток воспроизводился без потерь качества.
Идем дальше. Тест 21 микшер по 2 потока. В прошлом тестировании 21 микшер с RTMP потоками был максимальным числом микшеров для нашего сервера, посмотрим, на результаты с VOD потоками:
Тест пройден. Деградации стримов снова не зафиксировано, контрольный поток воспроизводился без потерь качества.
Тест 23 микшера по 2 потока:
Этот тест не пройден. Отмечается деградация стримов.
У нас остался еще один вариант теста между 21 и 23 микшерами. Тест 22 микшера по 2 VOD потока
В этом случае тест не пройден. Снова зафиксирована деградация стримов.
Значит, максимально число микшеров для двух VOD потоков на нашем сервере составляет 21 микшер — 21 чат комната для двух участников.
Результаты тестирования микшеров с VOD потоками в таблице ниже:
Число микшеров |
Число потоков в каждом микшере |
Результат теста |
---|---|---|
5 |
15 |
Пройден |
6 |
15 |
Не пройден |
12 |
2 |
Пройден |
18 |
2 |
Пройден |
21 |
2 |
Пройден |
22 |
2 |
Не пройден |
23 |
2 |
Не пройден |
24 |
2 |
Не пройден |
Тест третий: только звук
В двух предыдущих тестах мы тестировали микшеры к котором добавлялись полноценные видеопотоки - с видео и аудио компонентами. А что, если у нас не видео, а голосовой чат? Давайте посмотрим, сколько чат комнат мы сможем разместить на нашем сервере в этом случае.
Для этого теста будем использовать файл без видео с аудиодорожкой. На скриншоте ниже подробные параметры файла для теста:
Аудио потоки для микшера будем публиковать по технологии VOD (Video on Demand).
Скрипт для запуска тестирования:
#! /bin/bash
contentType="Content-Type:application/json"
mixer=24
stream=2
for i in `seq 1 $mixer`; do
data='{"uri":"mixer://mixer'$i'", "localStreamName":"mixer'$i'", "hasVideo":"false", "hasAudio":"true"}'
curl -X POST -H "$contentType" --data "$data" "http://localhost:8081/rest-api/mixer/startup" -nostdin -nostats </dev/null >/dev/null 2>&1 &
for j in `seq 1 $stream`; do
dataj='{"uri":"vod-live://audio-only.mp4", "localStreamName":"test'$i'-'$j'"}'
datai='{"uri":"mixer://mixer'$i'", "remoteStreamName":"test'$i'-'$j'", "hasVideo":"false", "hasAudio":"true"}'
curl -X POST -H "$contentType" --data "$dataj" "http://localhost:8081/rest-api/vod/startup" -nostdin -nostats </dev/null >/dev/null 2>&1 &
sleep 1s
curl -X POST -H "$contentType" --data "$datai" "http://localhost:8081/rest-api/mixer/add" -nostdin -nostats </dev/null >/dev/null 2>&1 &
done
done
Обратите внимание, что для этого теста мы отключаем создание видео потока при создании микшера и создание видеопотоков при добавлении потоков в микшер.
"hasVideo":"false"
Для отображения на графиках данных относительно аудиосоставляющей потоков добавим следующие метрики:
native_resources{instance="demo.flashphoner.com:8081", job="WCS_metrics_statistic", param="native_resources.audio_codecs"}
и
native_resources{instance="demo.flashphoner.com", job="WCS_metrics_statistic", param="native_resources.audio_resamplers"}
Скрипты и панели для Grafana можно скачать в разделе "Полезные файлы"
Начнем тестирование с 24 микшеров по 2 потока. Тестировать большее число потоков в микшере можно, но не совсем удобно в плане оценки воспроизведения контрольного стрима.
Для нашего сервера 24 микшера с видео --- это, теоретически, максимальное количество, и прошлые тесты показали, что с таким количеством микшеров сервер не справляется. В тестировании "Только аудио" видим, что сервер работает в нормальном режиме. Load Average 1 во время теста не превысил 10 единиц. Контрольный поток так же воспроизводился без слышимых ухудшений звука - без "кваканья" прерываний, ускорений и т.п.
Не будем вас утомлять долгими тестами. Для audio-only потоков нам удалось поднять 240 микшеров по 2 потока без деградации стримов и снижения качества выходных потоков. Для нашего сервера это 5 аудио микшеров на одно ядро CPU:
Результаты тестирования микшеров с audio-only потоками в таблице ниже:
Число микшеров |
Число потоков в каждом микшере |
Результат теста |
---|---|---|
24 |
2 |
Пройден |
48 |
2 |
Пройден |
240 |
2 |
Пройден |
Подводя итог
Сводные результаты трех тестов в таблице ниже:
Число микшеров |
Число потоков в каждом микшере |
Результат теста с RTMP потоками |
Результат теста с VOD потоками |
Результат теста с Audio-only потоками |
---|---|---|---|---|
4 |
15 |
Пройден |
- |
- |
5 |
15 |
Пройден |
Пройден |
- |
6 |
15 |
Не пройден |
Не пройден |
- |
8 |
15 |
Не пройден |
- |
- |
12 |
2 |
Пройден |
Пройден |
- |
18 |
2 |
Пройден |
Пройден |
- |
21 |
2 |
Пройден |
Пройден |
- |
22 |
2 |
Не пройден |
Не пройден |
- |
23 |
2 |
Не пройден |
Не пройден |
- |
24 |
2 |
Не пройден |
Не пройден |
Пройден |
48 |
2 |
- |
- |
Пройден |
240 |
2 |
- |
- |
Пройден |
Итак, максимальное количества микшеров для потоков с видео - 21 микшер по 2 потока. Основная работа сервера приходится на транскодинг видео потоков внутри микшера и сам процесс микширования. Транскодирование аудио тратит намного меньше ресурсов сервера, поэтому и количество микшеров для audio-only потоков на порядок больше, чем для видео.
В этой статье мы наглядно показали три сходных методики тестирования работы и подбора максимального числа микшеров в зависимости от задач и серверных мощностей.
Мы тестировали "классические" микшеры. В случае использования MCU результат тестирования будет отличаться, потому что в режиме MCU на каждый микшер создается столько дополнительных микшеров, сколько потоков входят в этот микшер. Например, один микшер с 10 входящими потоками породит в случае MCU 10 микшеров по 9 потоков в каждом. Итого будет 10x9 плюс 1x10 итого 11 микшеров.
На своих серверах вы можете получать другие значения, отличающиеся от наших тестов как в лучшую, так и в худшую сторону. На результаты тестирования могут влиять такие факторы, как:
качество, разрешение и битрейт потоков входящих в микшер;
состояние сети — скорость соединения, стабильность соединения, наличие широковещательного трафика и т.п.;
состояние серверного железа — тактовая частота процессора, количество реальных и/или "гипертрейдинговых" ядер, объем оперативной памяти и т.п.;
удаленность датацентра в котором размещены серверы от конечных пользователей (паблишеров и зрителей).
Сочетание всех этих факторов может влиять на результаты тестирования, поэтому при выборе сервера для продакшена рекомендуем обратить на это внимание и провести тестирование в условиях приближенных к вашей задаче.
Хорошего стриминга!
Полезные файлы
Панели для Grafana:
Настройки WCS:
Скрипт для получения кастомных метрик:
Скрипты для тестов:
Бонус "Как использовать панели для Grafana"
Скачайте и сохраните файлы .json из раздела выше.
-
Откройте файл на редактирование и замените IP адрес нашего сервера (172.16.40.23) на свой. Сохраните изменения в файле.
Откройте веб-интерфейс Grafana. Выберите из меню в левой части страницы пункт "Import":
4. На открывшейся странице нажмите кнопку "Upload JSON file" :
5. Выберите ранее отредактированный файл .json на вашем компьютере, затем нажмите кнопку "Import" на открывшейся странице:
Ссылки
WCS на Amazon EC2 - Быстрое развертывание WCS на базе Amazon
WCS на DigitalOcean - Быстрое развертывание WCS на базе DigitalOcean
WCS в Docker - Запуск WCS как Docker контейнера
Микширование видеопотоков - Функции сервера для реализации микширования потоков
Захват VOD из файла - Функции сервера по захвату видеопотоков из ранее созданного файла
Документация по быстрому развертыванию и тестированию WCS сервера
Документация по мониторингу информации о нагрузке и ресурсах
Документация по организации мониторинга с помощью Prometheus
Описание файла настроек flashphoner.properties
Описание файла настроек wcs-core.properties
Документация по управлению памятью в Java
Рекомендации по тонкой настройке сервера
Документация по подготовке к промышленной эксплуатации WCS
Документация по проведению нагрузочного тестирования с использованием захвата потоков по WebRTC/RTMP
Ovoshlook
Вы всегда пишете об MCU, но ни разу не рассматривали SFU как сервер. Это потому, что продукт не умеет в SFU?
fpn Автор
Умеет, но пока не для продакшна. Поэтому пока рекомендуем использовать MCU микшер.
Кроме того, микширование больше грузит сервер, но меньше - каналы пользователей.
Ovoshlook
Каналы пользователей можно не грузить ненужным трафиком если использовать правильные подходы и технологии ( simulcast, svc, speaker detection, framerate adjusting и тд ). SFU подход дешевле выходит. Кроме того на MCU дефакто почти невозможно построить распределенную систему виеоконференц связи особенно если сервис рамазан по различным географическим точкам и собеседники находятся на разных концах этих точек.
Так что это не оправдание использованию MCU ( по крайней мере для видео ). Поэтому стоит очтановиться на "не для продакшн пока".