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-серверы раздают поток конечным пользователям на их браузеры и мобильные приложения.

 

Scaling, Origin-Edge

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

The use of the RTMP Protocol when publishing the stream

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

Однако для нас межсерверное WebRTC началось не с масштабирования.

 

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

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

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

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

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

  1. Поднять процесс и открыть нужный урл
  2. Убить процесс.

 

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

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

 

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

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

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

Testing Server-Server as a WebRTC pulling

После этого мы вынесли управление 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 трансляций, и вот как она работает:

Origin-Edge scheme for scaling WebRTC broadcasts

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

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

The process of sending the video stream through a web example of 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 и начинаем его играть.

Stream from Edge server for WebRTC in the player

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

Support for WCS server a few ways to play

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

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

 

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

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

Web-interface REST client, the managing pull-sessions

С помощью консоли, можно тянуть отдельные WebRTC стримы, используя текущую ноду как Edge сервер.

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

Running load tests with performance evaluation in the Console

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

 

Ссылки

WCS5 — сервер Web Call Server 5, фигурирующий в статье

Two Way Streaming — пример трансляции видеопотока из браузера

WebRTC Player — пример воспроизведения видеопотока в браузере с возможностью смены технологий WebRTC, MSE, Flash, WSPlayer