Перейти к содержимому
Калькуляторы

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

 

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

 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

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

 

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

 

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

 

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

 

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

 

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

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

 

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;

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Итак, завел 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, а не хэшем. Не помогло.

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

 

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

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

 

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

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

proxy_cache_lock on;

proxy_cache_lock_timeout 60;

 

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

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

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

У меня урлы каналов следующего вида 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;
}

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте аккаунт или войдите в него для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!

Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас