WebRTC умеет работать Peer-to-Peer и Peer-to-Server, где в роли пира, как правило выступает браузер или мобильное приложение. В данной статье мы расскажем о работе WebRTC в режиме Server-to-Server, для чего это нужно и как это работает.

Масштабирование, Origin-Edge


Где может понадобиться межсерверное WebRTC? На ум сразу приходит паттерн Origin-Edge, который используется для масштабирования трансляции на большую аудиторию.


  1. Пользователь отправляет WebRTC видеопоток на Origin-WebRTC сервер с браузера или мобильного устройства.
  2. Origin-сервер рассылает поток по нескольким Edge-серверам.
  3. Edge-серверы раздают поток конечным пользователям на их браузеры и мобильные приложения.


В современных CDN для доставки видео активно используется протокол RTMP при публикации потока на Origin-сервер и при рассылке потока на Edge-сервера, а конечные пользователи получают картинку уже по HTTP.

Преимуществом WebRTC, по сравнению с данным подходом, может стать гарантированно низкая задержка трансляции, которой нельзя достичь средствами доставки RTMP / HTTP, особенно если ноды разнесены географически.
Однако для нас межсерверное WebRTC началось не с масштабирования.

Нагрузочные тесты


Они были всегда в том или ином виде. Автоматические и полуавтоматические, синтетические и близкие к тому, что делают пользователи. Мы использовали и используем нагрузочное тестирование для отлавливания многопоточных багов, контроля утечек ресурсов, оптимизаций, и многих других вещей, которые нельзя отловить на обычном тестировании.

На последних тестах мы поднимали Linux-серверы без GUI в облаке и запускали скрипты, стартующие много процессов браузера Google Chrome на виртуальном десктопе X11. Таким образом запускались реальные WebRTC-браузеры, которые тянули и играли WebRTC видеопотоки с Web Call Server, тем самым создавая нагрузку, максимально близкую к настоящей.  Для сервера это выглядело так, словно реальный пользователь открывал браузер и забирал видеопоток, полностью задействуя WebRTC-стек браузера, включая декодинг и рендеринг видео.

Недостатком этого способа тестирования была производительность тестовой системы. Достаточно тяжело запустить много процессов Chrome на одной Linux-системе, даже при использовании мощного сервера с мегаметрами памяти и CPU. В результате приходилось поднимать много серверов и как-то ими управлять / мониторить.

Другим ограничением было отсутствие гибкости — мы не могли  управлять процессами хрома. Было только две операции:

  1. Поднять процесс и открыть нужный урл
  2. Убить процесс. При открытии урла подгружалась HTML страница и происходило автоматическое соединение с сервером, уже средствами JavaScript, Websocket + WebRTC. Так моделировалась зрительская нагрузка.

Требовался гибкий инструмент нагрузочного тестирования, который позволил бы давать нагрузку на сервер, близкую к реальной, контролировать тестирование программно и обеспечить высокую производительность тестирования.

Тестирование WebRTC Server-Server


Мы пришли к выводу, что ноды нашего сервера сами могут стать генераторами нагрузки, если их правильно подцепить к тестируемым серверам.

Эта идея получила реализацию в виде WebRTC pulling. Один сервер WCS может вытянуть поток с другого сервера WCS по WebRTC. Для этого мы ввели внутреннюю абстракцию WebRTCAgent — объект, который поднимается на тестирующей ноде и тянет WebRTC-поток с тестируемой ноды, подключаясь к тестируемой ноде по Websocket+WebRTC.

После этого мы вынесли управление WebRTCAgent-ом на REST. В итоге нагрузочное тестирование свелось к вызову /pull — методов на REST интерфейсе тестирующей ноды.

При использовании межсерверного WebRTC нам удалось увеличить производительность нагрузочного тестирования примерно в 7 раз и значительно сократить использование ресурсов, по сравнению с той схемой, когда мы запускали процессы Google Chrome. 

Итак, у нас получилось тянуть WebRTC-потоки с других серверов. Тестирующий сервер подключался к тестируемому по Websocket, и как порядочный браузер, устанавливал ICE-соединение, DTLS и тянул SRTP потоки на себя, — получился true WebRTC pulling.

Оставалась совсем немного для получения полноценной модели Origin-Edge. Для этого нужно было пробросить такой pulling в движок WCS сервера как публикуемый поток, т.е. сделать его похожим на поток с веб-камеры, а такие потоки WCS уже умеет раздавать по всем доступным протоколам: WebRTC, RTMP, RTMFP, Websocket Canvas, Websocket MSE, RTSP, HLS.

Origin-Edge на WebRTC


Получилось, что мы делали межсерверный WebRTC для нагрузочного тестирования, но в результате реализовали Origin-Edge схему для масштабирования WebRTC трансляций, и вот как она работает:

Зеленой линией показано как проходит видео трафик. 

1. Пользователь из браузера или мобильного приложения, с помощью вебкамеры, отправляет WebRTC видеопоток с именем stream1 на сервер WCS1 — Origin. Процесс отправки видеопотока с помощью веб примера Two Way Streaming выглядит так:

А это JavaScript код, который отвечает за публикацию видеопотока через Web API (Web SDK):

session.createStream({name:'steram1',display:document.getElementById('myVideoDiv')}).publish();

2.  Далее мы обращаемся к серверу WCS2 — Edge по REST/HTTP API и даем команду забрать видеопоток с Origin-сервера.

/rest-api/pull/startup

{

                uri: wss://wcs1-origin.com:8443

                remoteStreamName: stream1,

                localStreamName: stream1_edge,

}

Сервер WCS2 подключается по вебсокетам к серверу WCS1 по адресу wss://wcs1-origin.com:8443 и принимает поток с именем stream1 по WebRTC.

После этого можно выполнить REST-команду

/rest-api/pull/find_all

чтобы вывести все текущие pull-подключения.

Или команду

/rest-api/pull/terminate

чтобы закрыть pull-соединение с Origin WebRTC сервером.

3. И наконец, забираем поток с Edge-сервера по WebRTC в плеере. Вводим имя потока stream1_edge и начинаем его играть.

WCS — сервер поддерживает несколько способов воспроизведения. Чтобы поменять технологию, просто тащим вверх MSE или WSPlayer чтобы играть поток не по WebRTC, а по MSE (Media Source Extensions) или в WSPlayer (Websocket — плеер для iOS Safari).

Таким образом, схема Orign-Edge отработала и мы получили масштабируемость WebRTC-сервера с низкой задержкой.

Нужно заметить, что масштабируемость работала и раньше по RTMP. WCS сервер умеет делать ре-публикацию входящих WebRTC-потоков на один или несколько серверов по протоколу RTMP. В данном случае, поддержка межсерверного WebRTC стала шагом к снижению общей задержки системы.

И снова про нагрузочное тестирование


Для нормального нагрузочного тестирования осталось написать Web-интерфейс в виде REST-клиента, управляющего pull-сессиями. Этот интерфейс был назван Console и принял следующий вид:


С помощью консоли, можно тянуть отдельные WebRTC стримы, используя текущую ноду как Edge сервер. Через этот же интерфейс можно добавить одну или несколько нод и запустить на них нагрузочные тесты с оценкой производительности.


Еще предстоит немало сделать и отдебажить. В частности интересно поработать с динамическими битрейтами на межсерверном WebRTC-канале и сравнить межсерверную  проходимость с RTMP. Но уже сейчас у нас есть Orign-Edge на WebRTC и правильные нагрузочные тесты, дающие близкую к реальной нагрузку, что не может не радовать!

Ссылки


WCS5 — WebRTC сервер Web Call Server 5
Two Way Streaming — пример трансляции видеопотока из браузера
WebRTC Player — пример воспроизведения видеопотока в браузере с возможностью смены технологий WebRTC, MSE, Flash, WSPlayer

Комментарии (0)