Jump to content
Калькуляторы

Балансировка нагрузки на HLS-стримеры

Потихоньку заводим у себя на сети HLS. Как известно, юникаст поедает довольно много трафика. Поэтому есть желание сделать несколько стримеров по сети чтобы отправлять туда ближайших пользователей. А на стримеры медиапотоки с центрального узла загонять мультикастом.

 

И вот тут есть затык. Мы используем Stalker middleware и одноразовые ссылки. В теории можно смотреть на адрес клиента и отправлять его на ближайший стример. В Сталкере есть балансировка по GeoIP и количеству клиентов на стример. Но балансировки просто на основе адресе клиента нет. Можно, конечно, переделать код Сталкера, но очень не хочется этого делать т.к. во все следующие версии придется этот код портировать. В общем, вариант на крайний случай.

 

И тут родилась идея с http-редиректом. Ставим nginx и вот такой конструкцией:

 


geo $redir_user {
       default 0;
       10.0.100.0/24 1;
   }

server {
       listen 80;
       server_name  localhost;

       if ($redir_user) {
               rewrite ^ $scheme://10.20.1.67:8888$request_uri break;
       }
       }

 

 

 

при помощи модуля geo смотрим на адрес клиента и затем через rewrite перенаправляем клиента на нужный стример. Собрал демку, попробовал - в VLC и на приставках вполне работает.

 

Есть еще вариант с HAProxy. Он тоже умеет HTTP Redirect и кроме балансировки может определять живой стример или нет и таким образом обеспечивать отказоустойчивость. Пока не тестил, но думаю, что тоже будет работать.

 

Так что вопрос к публике - а кто решал подобного рода задачи? Какие подводные камни? И в верном ли направлении я двигаюсь?

Share this post


Link to post
Share on other sites

Если вы используете HLS - может проще сделать кеширующий прокси?

плейлисты не кешируете, ts кешируете. Как отправлять абонентов на тот или иной кеш зависи от сети и уже можно пофантазировать.

Share this post


Link to post
Share on other sites

О прокси я как-то не думал если честно. Можно тот же nginx приспособить. Думаю должно взлететь.

 

Есть еще идей с dns view.

Share this post


Link to post
Share on other sites

в flussonic один из вариантов — это именно такая балансировка с редиректом. Работает.

Share this post


Link to post
Share on other sites

Смотря что и как отдавать.

Главное сетевуха, дальше если раздавать из tmpfs используя sendfile() то будет шустро и маложруче.

Share this post


Link to post
Share on other sites

в flussonic один из вариантов — это именно такая балансировка с редиректом. Работает.

 

Максим, а вы не могли бы подробнее описать механизм кластеризации во Флуссонике? У вас на сайте это описано как-то неочевидно.

Share this post


Link to post
Share on other sites

nginx легко выдаст 30 Гбит на сервак. Главное проц получше

 

Тут есть еще один момент. Я бы хотел резервировать сами стримеры т.к. это обеспечивает отказоустойчивость. В случае же кеширующего прокси отказ стримера убивает все вещание...

 

 

 

Share this post


Link to post
Share on other sites

Резервировать стримеры безусловно надо.

Однако что будет когда у вас еще трафика прибавится? А когда еще? Будете добавлять каждый раз новый стример.

 

С кешерами вам достаточно иметь 1+1 на стримерах и мощности увеличивать только на уровне кешей. Резервирование origin на них же.

 

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

Share this post


Link to post
Share on other sites

Ставите 2-3 стримера, которые только выдают HLS потоки.

 

Ставите N прокси nginx, которые со стримеров берут потоки. И вот эти N-прокси и записываете в Сталкер как сервера для абонентов.

 

В настройке nginx есть некоторые ньюансы, когда доберетесь до этого - пишите тут вопросы.

 

Лично я в nginx настроил кеширование в ramdisk. Если захочется писать кеш на диск, то обязательно ставить отдельный SSD, но для меня это бессмысленно. Кеш никакой ценности не имеет и в любой момент может быть прогрет с нуля.

 

И, да, никакого мультикаста вам тут в принципе не нужно. Nginx будет забирать поток с апстрима только если есть клиенты, которые его тянут. HLS специально создан для такой конфигурации сети.

Share this post


Link to post
Share on other sites

Sonne, спасибо за комментарии. Есть сразу ряд вопросов.

 

1. Я так понимаю, что на nginx можно реализовать вполне рабочий on demand?

2. Какой именно ramdisk вы используете? ramdisk, ramfs, tmpfs?

3. Через прокси получилось завести одноразовые ссылки для авторизации просмотра?

Share this post


Link to post
Share on other sites

Рабочий основной конфиг.

 

tmpfs           7.0G  3.0G  4.1G  42% /var/cache/nginx/ram

 

cat /etc/nginx/nginx.conf
user nginx;
worker_processes auto;
worker_rlimit_nofile 65535;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

events {
   worker_connections 1024;
}

http {
   log_format main  '$remote_addr - $remote_user [$time_local] "$request" '

   access_log  /var/log/nginx/access.log  main;

   sendfile            on;
   tcp_nopush          on;
   tcp_nodelay         on;
   keepalive_timeout   65;
   types_hash_max_size 2048;

   include             /etc/nginx/mime.types;
   default_type        application/octet-stream;

   proxy_cache_path /var/cache/nginx/ram keys_zone=ram:10m inactive=1m max_size=6656m;

   include /etc/nginx/conf.d/*.conf;

Share this post


Link to post
Share on other sites

Итак, завел nginx в режиме прокси. Настройки сервера (кэша) от Blaar.

 

Настройки виртуального хоста:

 

server {
       listen 80;
       server_name  localhost;

       location / {
       proxy_pass http://10.20.1.67:8888;
       proxy_cache ram;

       }
       }

 

Запускаем два экземпляра vlc и открываем там один и тот же hls url. В логе nginx вижу, что клиенты запрашивают одинаковые чанки (имя и размер).

 

10.0.100.100 - - [30/May/2017:12:29:44 +0300] "GET /pervii_kanal/36143069.m3u8 HTTP/1.1" 200 152 "-" "VLC/2.2.4 LibVLC/2.2.4"
10.0.100.100 - - [30/May/2017:12:29:44 +0300] "GET /pervii_kanal/138.ts HTTP/1.1" 200 3778612 "-" "VLC/2.2.4 LibVLC/2.2.4"
10.0.100.100 - - [30/May/2017:12:29:44 +0300] "GET /pervii_kanal/139.ts HTTP/1.1" 200 3780116 "-" "VLC/2.2.4 LibVLC/2.2.4"
10.0.100.100 - - [30/May/2017:12:29:45 +0300] "GET /pervii_kanal/140.ts HTTP/1.1" 200 3786132 "-" "VLC/2.2.4 LibVLC/2.2.4"
10.0.100.100 - - [30/May/2017:12:29:47 +0300] "GET /pervii_kanal/62454622.m3u8 HTTP/1.1" 200 152 "-" "VLC/2.2.4 LibVLC/2.2.4"
10.0.100.100 - - [30/May/2017:12:29:48 +0300] "GET /pervii_kanal/139.ts HTTP/1.1" 200 3780116 "-" "VLC/2.2.4 LibVLC/2.2.4"
10.0.100.100 - - [30/May/2017:12:29:48 +0300] "GET /pervii_kanal/140.ts HTTP/1.1" 200 3786132 "-" "VLC/2.2.4 LibVLC/2.2.4"
10.0.100.100 - - [30/May/2017:12:29:48 +0300] "GET /pervii_kanal/141.ts HTTP/1.1" 200 3771656 "-" "VLC/2.2.4 LibVLC/2.2.4"

 

Однако судя по логам Астры, с которой nginx забирает чанки, nginx ничего не кеширует и просто дважды запрашивает одно и то же. На Астре поправил механизм именования чанков, теперь они именуются по sequence, а не хэшем. Не помогло.

 

Что я делаю не так?

Share this post


Link to post
Share on other sites

Сам себе и отвечаю. Нужно было включить игнорирование no-cache в запросах клиента. Это приводит к тому, что m3u8 тоже кешируется. Поэтому надо *.m3u8 пропустить мимо кэша.

 

В итоге nginx.conf:

 

user www-data;
worker_processes auto;
worker_rlimit_nofile 65535;
pid /run/nginx.pid;

events {
       worker_connections 1024;
       # multi_accept on;
}

http {

       sendfile on;
       tcp_nopush on;
       tcp_nodelay on;
       keepalive_timeout 65;
       types_hash_max_size 2048;

       include /etc/nginx/mime.types;
       default_type application/octet-stream;


       log_format cache        '$remote_addr - $upstream_cache_status [$time_local]  '
                               '"$request" $status $body_bytes_sent '
                               '"$http_referer" "$http_user_agent"';

       access_log /var/log/nginx/access.log;
       access_log /var/log/nginx/access.cache.log cache;
       error_log /var/log/nginx/error.log;

       proxy_cache_path /var/cache/nginx/ram levels=1:2 keys_zone=ram:10m inactive=1m max_size=1024m;
       proxy_cache_min_uses 1;
       proxy_ignore_headers X-Accel-Expires;
       proxy_ignore_headers Expires;
       proxy_ignore_headers Cache-Control;

       gzip off;

       include /etc/nginx/conf.d/*.conf;
       include /etc/nginx/sites-enabled/*;
}

 

 

 

В настройках хоста:

 

server {
       listen 80;
       server_name  localhost;

       location / {
       proxy_pass http://10.20.1.67:8888;
       proxy_cache ram;
       proxy_cache_key $host$uri$is_args$args;
       proxy_cache_valid 200 2m;
       }

       location ~* \.(m3u8)$ {
       proxy_cache off;
       expires -1;
       proxy_pass http://10.20.1.67:8888;
       }


}

 

 

На коленке все вроде работает, но скорее всего придется тюнить конфиг. Пока неизвестно как разные hls-клиенты себя ведут.

Share this post


Link to post
Share on other sites

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

 

Результат кеширования будет зависит от того, по какому ключу вы и кешируете. У нас это $host$uri;

на live контент hit ratio под 90%

 

Конфиг тюнится в зависимости уже от нужд. Еще про тюнинг OS не забывайте.

Например можно (даже нужно) поставить

proxy_cache_lock on;

proxy_cache_lock_timeout 60;

 

proxy_temp_path - должно находиться в одной fs где и кеш для быстроты.

 

Ну и worker уже добавлять, когда станет мало. на 4х ядрах и 1024 воркерах - рабочая нагурзка около 8 Гб/с

Share this post


Link to post
Share on other sites

Подниму тему.

Коллеги, подскажите пожалуйста с настройкой прокси.

У меня урлы каналов следующего вида http://server:port/channel/video.m3u8?id=password

Как правильно изменить настройки хоста в nginx, чтобы не кешировал плейлист?

location ~* \.(m3u8)$ {
       proxy_cache off;
       expires -1;
       proxy_pass http://server:port/channel/video.m3u8?id=password;
}

 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.