Создаем живую потоковую CDN для видеотрансляций WebRTC с низкой задержкой


    Где может потребоваться трансляция с гарантированной низкой задержкой? — на самом деле, много где. Например в онлайн видео-аукционах. Представьте себя ведущим такого мероприятия.
    — «Двести тыыыысяч рааааз»
    — «Продано!»

    С высокой задержкой вы успеете сказать «двести тысяч три» и продать лот еще до того как видео дойдет до участников. Чтобы участники аукциона успели вовремя среагировать, задержка должна быть гарантированно низкой.

    В общем, низкая задержка жизненно необходима в любом около игровом сценарии, будь-то онлайн видео аукцион, видеотрансляция скачек с лошадками или интеллектуальная онлайн игра «Что Где Почему» — и там и там требуется гарантированно низкая задержка и передача видео и аудио в реальном времени.

    Почему CDN


    Один сервер зачастую не способен доставить потоки всем желающим просто по той причине, что все зрители географически распределены и имеют каналы связи разной пропускной способности. Кроме этого, одного сервера может быть недостаточно по ресурсам. Поэтому нужна гроздь серверов, которые занимаются доставкой потока. А это и есть CDN — сеть доставки контента. Контентом в данном случае будет потоковое видео с низкой задержкой, которое передается с веб-камеры транслирующего пользователя зрителям.

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


    В этой схеме используется минимальное необходимое количество серверов: 4.

    1) Origin + LB

    Это сервер, который принимает транслируемый видеопоток с веб-камеры пользователя.

    Отправка потока в браузере может выглядеть так:


    Это пример отправки видеопотока с веб-страницы, открытой в браузере Google Chrome. Поток отправляется на тестовый сервер origin.llcast.com.

    После того как Origin принял видеопоток, он ретранслирует принятый поток на два сервера Edge1 и Edge2. Сам Origin-сервер потоки не раздает.

    Для упрощения, в данной схеме мы возложили на Origin роль балансировщика нагрузки (LB). Он опрашивает edge-ноды и сообщает подключившимся клиентам-зрителям к какой из нод им следует подключиться.

    Балансировка работает так:



    1. Браузер обращается к балансировщику (в данном случае совпадает с Origin).
    2. Балансировщик возвращает один из серверов: Edge1 или Edge2.
    3. Браузер устанавливает соединение с сервером Edge2 (в примере), по протоколу Websocket.
    4. Сервер Edge2 отдает видео трафик по WebRTC.

    Origin периодически опрашивает серверы Edge1 и Edge2, проверяя их доступность и собирает данные по нагрузке. Этого достаточно чтобы принять решение, на какой из серверов «приземлить» новый коннект. Если один из серверов по какой-то причине недоступен, коннекты будут «приземляться» на оставшийся Edge-сервер.

    2) Edge1 и Edge2

    Это серверы, которые занимаются непосредственно раздачей аудио и видео трафика зрителям. Каждый из них получает поток от Origin-сервера и каждый предоставляет Origin-серверу информацию о своей загрузке.

    3) TURN relay — сервер.

    Чтобы обеспечить действительно низкую задержку, вся вышеописанная схема доставки аудио и видео работает по протоколу UDP. Однако данный протокол может быть закрыт на сетевых экранах и иногда приходится пускать весь трафик через HTTPS порт 443, который как правило, открыт. Для этого используется TURN relay. Если нормальное соединение по UDP не проходит, видео пойдет через TURN и по TCP. Это неизбежно ухудшит задержку, но если большая часть ваших пользователей-зрителей находится за корпоративными файрволами, то так или иначе придется использовать TURN для WebRTC либо другой способ доставки контента по TCP, например Media Source Extension / Websocket.

    В данном случае, мы выделяем 1 сервер специально для прохождения файрволов. Он будет раздавать видео по WebRTC / TCP для тех зрителей, кому не посчастливилось получить нормальное соединение по UDP.

    Географическое распределение


    Origin-сервер будет находиться в датацентре Франкфурта. В то время как Edge1 сервер будет находиться в Нью-Йорке, а Edge2 будет расположен в Сингапуре. Таким образом мы получаем распределенную трансляцию, охватывающую большую часть земного шара по протяженности.


    Установка и запуск серверов


    Для недорогого тестирования, возьмем виртуальные серверы Digital Ocean.

    Заготовим 4 дроплета (виртуальных сервера) на DO, по 2 Gb RAM каждый. Это обойдется нам в 12 центов в час, а одни сутки примерно в 3 доллара.


    В качестве Origin и Edge1, Edge2 — серверов, будет использоваться WebRTC сервер WCS5. Его нужно скачать и установить на каждый из дроплетов.

    Процесс установки WCS-сервера выглядит так:

    1) Скачиваем дистрибутив.

    wget https://flashphoner.com/download-wcs5-server.tar.gz

    2) Распаковываем и устанавливаем.

    tar -xvzf download-wcs5-server.tar.gz
    cd FlashphonerWebCallServer-5.0.2505
    ./install.sh

    Не забываем установить haveged, который может потребоваться для ускорения запуска WCS сервера на Digital Ocean.

    yum install epel-release
    yum install haveged
    haveged chkonfig on
    haveged

    3) Запускаем.
    service webcallserver start

    4) Создаем сертификаты Let’sencrypt

    wget https://dl.eff.org/certbot-auto
    chmod a+x certbot-auto
    certbot-auto certonly

    Certbot положит сертификаты в папку /etc/letsencrypt/live

    Пример:

    /etc/letsencrypt/live/origin.llcast.com

    6) Импортируем сертификаты Let’sencrypt

    ├── cert.pem
    ├── chain.pem
    ├── fullchain.pem
    ├── fullchain_privkey.pem
    ├── privkey.pem
    └── README

    Из этих файлов нам потребуются всего два: цепочка сертификатов и приватный ключ:

    • fullchain.pem
    • privkey.pem


    Загружаем их через Dashboard / Security / Certificates. Чтобы зайти в админку WCS-сервера, открываем адрес origin.llcast.com:8888, где origin.llcast.com — доменное имя вашего WCS сервера.

    Результат импорта выглядит так:


    Все готово. Импорт прошел успешно и теперь нужно выполнить короткий тест чтобы убедиться, что все работает. Заходим в Dashboard сервера в демо — пример Two Way Streaming. Нажимаем кнопку Publish и через несколько секунд Play. Убеждаемся что сервер работает, принимает потоки и отдает их на воспроизведение.


    После того как проверили один сервер, делаем с остальными двумя (Edge1 и Edge1) тоже самое. Устанавливаем на них WCS5, получаем сертификаты Let's Encrypt и импортируем в установленный WCS-сервер для корректной работы. В завершение каждой установки проводим простой тест, который показывает, что сервер откликается и играет потоки.

    В результате мы настроили три сервера, доступные по следующим адресам:


    Конфигурация Origin-сервера


    Остается сконфигурировать и объединить серверы в CDN. Начинаем с сервера Origin.

    Как мы уже писали выше, Origin является в том числе и балансировщиком. Находим в конфигах файл WCS_HOME/conf/loadbalancing.xml и прописываем в нем Edge-ноды. В результате конфиг будет выглядеть так:

    <loadbalancer mode="roundrobin" stream_distribution="webrtc">
            <node id="1">
                    <ip>edge1.llcast.com</ip>
                    <wss>443</wss>
            </node>
            <node id="2">
                    <ip>edge2.llcast.com</ip>
                    <wss>443</wss>
            </node>
    </loadbalancer>

    Данный конфиг описывает следующие настройки:

    • На какие ноды должен ретранслироваться видеопоток с Origin (edge1 и edge2).
    • По какой технологии будет происходить ретрансляция (webrtc).
    • Какой порт нужно использовать для Websocket-соединения с edge-нодой (443).
    • Режим балансировки — по кругу (roundrobin).

    На текущий момент поддерживается два способа ретрансляции Origin — Edge, которые задаются атрибутом stream_distribution, это:

    • webrtc
    • rtmp

    Выставляем здесь webrtc, т.к. нам требуется низкая задержка. Далее необходимо сказать Origin-серверу, что он будет заниматься балансировкой. Включаем балансировщик в конфиге WCS_HOME/conf/server.properties

    load_balancing_enabled =true

    Кроме этого, назначим балансировщику порт 443, чтобы подключающиеся клиенты могли получать данные от балансера по стандартному порту HTTPS, опять же для успешного прохождения файрволов. В этом же конфиге server.properties добавляем

    https.port=443

    Далее выполняем перезагрузку WCS-сервера чтобы применить сделанные изменения.

    service webcallserver restart

    В результате мы включили балансировщик и настроили его на порт 443 в конфиге server.properties, а также настроили ретрансляции Origin-Edge в конфиге loadbalancing.xml.

    Конфигурация Edge-серверов


    Edge-серверы не требуют особой конфигурации. Просто принимают поток с Origin-сервера, как если бы пользователь отправлял этот поток с веб камеры напрямую на данный Edge-сервер.

    Хотя одну настройку добавить все же придется. Нужно переключить Websocket — порт раздающих видео серверов на 443 для лучшей проходимости через файрволы. Если Edge-серверы будут принимать соединения на порту 443 по HTTPS и TURN будет делать тоже самое, мы получим решение с обходом файрвола, которое поможет увеличить доступность трансляции для корпоративных пользователей за файрволами.

    Меняем конфиг WCS_HOME/conf/server.properties и выставляем настройку

    wss.port=443

    Выполняем перезагрузку WCS-сервера чтобы применить сделанные изменения.

    service webcallserver restart

    На этом настройка Edge-сервера завершена и можно приступать к тестированию CDN.

    Трансляция с веб-камеры на Origin


    Пользователи нашей мини-CDN делятся на стримеров и плееров. Стримеры — транслируют видео на CDN, а плееры — зрители, это видео играют. Интерфейс стримера может выглядеть так:


    Самый простой способ протестировать этот интерфейс, открыть демо Two Way Streaming на Origin-сервере.

    Пример стримера на Origin-сервере:

    https://origin.llcast.com:8888/demo2/two-way-streaming

    Для тестирования нужно установить Websocket соединение с сервером по кнопке Connect и далее отправить видеопоток на сервер по кнопке Publish. В результате, если все верно настроено, поток появится на серверах Edge1 и Edge2 и его можно будет с них проиграть.

    Данный интерфейс всего лишь демо HTML-страницы на основе клиентского JavaScript API (Web SDK) и его можно кастомизировать и привести к любому дизайну с помощью HTML / CSS.

    Воспроизведение потока с серверов Edge1 и Edge2



    Интерфейс плеера можно взять с одного из серверов edge1.llcast.com или edge2.llcast.com — пример Demo / Embed Player

    Тестирование можно провести, подключившись напрямую к edge-серверу по этим ссылкам:

    Edge1

    https://edge1.llcast.com:8888/demo2/embed-player

    Edge2

    https://edge2.llcast.com:8888/demo2/embed-player

    Плеер устанавливает Websocket-соединение с указанным Edge-сервером и забирает с этого сервера видеопоток по WebRTC. Обратите внимание, что на Edge серверах Websocket соединение устанавливается по порту 443, который был сконфигурирован выше для проходимости через файрволы.

    Этот плеер можно встроить в сайт в виде iframe либо провести более плотную интеграцию с использованием JavaScript API и разработкой собственного дизайна на HTML / CSS.

    Подключение балансировщика нагрузки в плеер


    Выше мы убедились в том, что Origin получает видеопоток и реплицирует этот поток на два Edge-сервера. Мы подключились к каждому из Edge-серверов по отдельности и протестировали воспроизведение потока.

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

    Для этого в JavaScript коде плеера нужно указать адрес балансировщика — lbUrl. Если его указать, то пример Embed Player будет сначала обращаться к балансировщику и брать с него рекомендованный адрес сервера, и уже после этого устанавливать соединение с полученным адресом по протоколу Websocket.

    URL балансировщика легко протестировать. Открываем его в браузере:

    https://origin.llcast.com/?action=server_list

    Результатом будет кусок JSON, в котором балансировщик показывает рекомендуемый Edge-сервер.

    {
    "server": "edge1.llcast.com",
    "flash": "1935",
    "ws": "8080",
    "wss": "443"
    }

    В данном случае балансировщик вернул первый сервер edge1.llcast.com и показал, что с сервером можно установить защищенное Websocket соединение (wss) по порту 443.

    Если обновлять страницу в браузере, балансировщик будет отдавать то один Edge-сервер, то другой, по кругу. Так работает roundrobin.

    Осталось включить балансировщик в плеере. Для этого в коде плеера player.js добавляем параметр lbUrl при установке сессии с сервером:

    Flashphoner.createSession({urlServer: urlServer, mediaOptions: mediaOptions, lbUrl:'https://origin.llcast.com/?action=server_list'})

    Полный код плеера приведен по ссылке ниже:

    https://edge1.llcast.com:8888/client2/examples/demo/streaming/embed_player/player.js

    Проверяем работу балансировщика и убеждаемся в том, что он корректно раскидывает соединения по нодам edge1.llcast.com и edge2.llcast.com. Для этого просто обновляем страницу плеера и смотрим в Developer Tools вкладку Network, где виден коннект к балансировщику и к серверу edge1.llcast.com (выделено красным).

    https://edge1.llcast.com:8888/client2/examples/demo/streaming/embed_player/player.html



    Финальный тест


    Мы настроили Orign-Edge, ретрансляции, балансировку и подключение плеера на основе данных балансировщика. Осталось собрать все воедино и провести тест, демонстрирующий работу получившейся CDN.

    1. Открываем страницу стримера

    https://origin.llcast.com:8888/client2/examples/demo/streaming/two_way_streaming/two_way_streaming.html

    Отправляем видеопоток с веб-камеры на Origin сервер, под именем stream1 из браузера Google Chrome.


    Заходим в Dev Tools — Network и убеждаемся, что транслирующий браузер подключился к Origin-серверу и отправил на него поток.


    2. Открываем страницу плеера на Edge-сервере и играем поток stream1.

    https://edge1.llcast.com:8888/client2/examples/demo/streaming/embed_player/sample.html


    Видим, что балансировщик выдал edge1.llcast.com и поток в данный момент забирается с него.



    Далее обновляем страницу еще раз и балансировщик подключает плеер к серверу edge2.llcast.com, который находится в Сингапуре.


    Таким образом мы справились с первой задачей и завершили настройку географически распределенной CDN на базе WebRTC с низкой задержкой.

    Далее нужно проверить задержку и убедиться, что она является действительно невысокой относительно RTT. Хорошей задержкой в глобальной сети является стабильная, не превышающая 1 секунды задержка. Проверим что получилось у нас.

    Измеряем задержку


    Предполагаем что значение задержки будет отличаться в зависимости от того, к какому серверу мы подключились плеером — на Edge1 в Нью Йорке или на Edge2 в Сингапуре.

    Для того чтобы иметь какую-то точку отсчета, составим карту RTT, чтобы понимать как устроена наша тестовая сеть и чего ждать от ее участников. Предполагаем, что особых потерь нет и измеряем только время пинга (RTT).


    Как видите, наша тестовая сеть совсем глобальная и неоднородная по задержке. Стример и плеер будут находиться в Новосибирске. Пинг до сервера Edge1 в Нью Йорке составит 170 ms, а до Edge2 в Сингапуре 306 ms.

    Будем учитывать эти данные при анализе результатов тестирования. Например понятно, что если мы будем транслировать поток на Origin во Франкфурте, передавать его на Edge 2 в Сингапуре и забирать из Новосибирска, то задержка ожидается никак не меньше (90 + 183 + 306) / 2 = 290 миллисекунд.

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

    Отправляем поток на Origin и делаем несколько скриншотов при воспроизведении с
    Edge1 — сервера. Слева расположено локальное видео с камеры с нулевой задержкой, а справа видео, которое пришло на плеер через CDN.

    Результаты тестов:

    Test number

    Latency (ms)

    1

    386

    2

    325

    3

    384

    4

    387

    Average latency: 370 ms




    Как видите, средняя задержка видеопотока по пути доставки контента Новосибирск (стример) — Франкфурт (Origin) — Нью Йорк (Edge1) — Новосибирск (плеер), составила 370 миллисекунд. RTT по этому же пути = 90 + 84 + 170 = 344 миллисекунды. Таким образом получаем результат 0.9 RTT, что очень и очень неплохо для доставки живого видеопотока, учитывая, что идеальным результатом был бы 0.5 RTT.


    Задержка и RTT для маршрута Edge1, Нью Йорк

    Теперь заберем тот же поток с сервера Edge2 в Сингапуре и поймем как повышение RTT влияет на задержку. Делаем аналогичный тест с сервером Edge2 и приходим к следующим результатам:

    Test number

    Latency (ms)

    1

    436

    2

    448

    3

    449

    Average latency: 444 ms



    Из этого теста видим, что соотношение задержки к RTT около 0.7, т.е лучше, чем в предыдущем тесте.


    Задержка и RTT для маршрута Edge2, Сингапур

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

    Так или иначе, цель построения географически распределенной CDN с задержкой менее секунды достигнута и есть поле для будущих тестов и оптимизаций.

    В заключение


    В итоге, мы развернули три сервера: Origin, Edge1 и Edge2, а не четыре, как обещали в начале статьи. Настройка, конфигурация и тестирование TURN сервера за файрволом сильно увеличивают и без того раздутый материал. В связи с этим полагаем, что есть смысл оформить его в отдельной статьей. Пока же просто не забываем, что четвертым сервером в этой схеме может быть TURN-сервер, который обслуживает WebRTC браузеры по порту 443, обеспечивая проходимость через файрволы.

    Итак, CDN для WebRTC потоков настроена и задержка измерена. Финальная схема работы вышла такой:


    Как можно эту схему улучшить и расширить? Можно улучшать в ширину. Например добавляем несколько Origin-серверов и ставим балансировщик между ними. Таким образом мы будем балансировать не только зрителей, но и стримеров — тех, кто непосредственно транслирует контент с веб-камер:


    CDN пока открыта в демо-доступе на домене llcast.com. Возможно скоро заморозим ее, и демо ссылки работать перестанут. Поэтому если появится желание измерить задержку — добро пожаловать. Хорошего стриминга!

    Ссылки


    https://origin.llcast.com:8888 — демо сервер Origin
    https://edge1.llcast.com:8888 — демо сервер Edge1
    https://edge2.llcast.com:8888 — демо сервер Edge2
    Two Way Streaming — демо интерфейс трансляции потока с веб камеры на Origin.
    Embed Player — демо интерфейс плеера с балансировщиком между Edge1 и Edge2
    WCS5 — WebRTC сервер, на основе которого построена CDN
    Flashphoner 16,66
    Компания
    Поделиться публикацией
    Комментарии 0

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

    Самое читаемое