Есть площадка с видео контентом, где посещаемость около 500 тысяч уников в сутки. Видео у себя не хранили, а любезно заимствовали с сайтов «партнеров». Ну как заимствовали: в реальном времени парсили с сайта ссылки на видеопотоки и вставляли в свой плеер.
В такой схеме было несколько ключевых проблем:
- Нужно поддерживать работоспособность парсеров в режиме 24/7 для всех сайтов партнеров, а их не один десяток;
- Видео иногда удаляются;
- После определённой нагрузки, а иногда спонтанно, некоторые видео начинают требовать ретрансляции.
В определённый момент поняли, что так жить больше нельзя и нужно раздавать видео со своих серверов. По примерной оценке размер видео был 4-5TB и максимальный порт в час пик около 5-7Gbit/s (после запуска цифры оказались примерно такими же).
Кратко о структуре
Главный сервер:
- Хранит все видео;
- Отвечает за загрузку видео с сайта партнера;
- Распределяет видео по раздающим серверам;
- Считает статистику популярности видео;
- Отдает плей-листы для плеера;
- Является балансировщиком для выбора раздающего сервера;
Раздающий сервер:
- Раздает видео.
Видео — это все качества (240, 360, 480 и 720) одного видео + фото заставки. Все видео конвертируем в mp4 (H.264 видео и AAC аудио), фото заставки в jpeg.
Все сервера имеют две сетевые карты, каждая с портом 1Gbit/s. Внешняя сетевая карта для раздачи, а внутренняя для распределения видео с главного на раздающие сервера.
Главный сервер один, а раздающих может быть любое количество. Раздающие сервера объедены в группы и один сервер может принадлежать только одной группе. Видео может входить только в одну группу. При запросе видео, балансировка идет только между серверами группы, к которой принадлежит запрашиваемое видео.
Бэкенд реализован на yii2.
Загрузка нового видео
На главный сервер прилетает запрос по API с ссылкой на видео, которое нужно скачать. Если видео поддается парсингу, то оно добавляется в стек на скачивание. После скачивания оно попадает в стек для распределения на раздающие сервера. Перед загрузкой на раздающий сервер для видео выбирается группа (выбирается один раз и больше не меняется).
На данный момент, группа выбирается банальным образом. Идет равномерное распределение по количеству видео. Так как размер видео разный, то если группа заполнена под завязку то она выпадает из дальнейшего распределения.
После скачивания видео оно конвертируется в mp4 (H.264 видео и AAC аудио) с помощью ffmpeg. Чтобы видео быстро стартовало в плеере его нужно прогнать через MP4Box. Это необходимо из-за того, что ffmpeg помещает “moov-атомы” (мета-информацию о видео) в конец файла, однако, чтобы пользователь имел возможность просматривать видео не дожидаясь его полной загрузки, эти атомы должны быть вначале файла.
Скачивание файлов на главный сервер и их распределение по раздающим серверам работает в несколько потоков. При этом видео скачивается параллельно во всех качествах.
Для многопоточности использую стек для заданий (FIFO) + демон, который поддерживает нужное количество потоков. Поток – это запущенный демоном php через exec. Все добро сделал
Как только, хотябы одно качество, видео загрузится на все раздающие сервера в своей группе оно становится доступным для стриминга.
Хранение видео
Рассмотрим хранения файлов на примере видео с id = 3044:
videoHash – это md5(id)
videoHashChar2 – первые два символа от videoHash
quality – качество видео (240, 360, 480, 720)
storage/image/<b>{videoHashChar2}</b>/<b>{videoHash}</b>.jpg storage/video/<b>{videoHashChar2}</b>/<b>{videoHash}</b>.<b>{quality}</b>.mp4 md5(3044) = b8af7d0fbf094517781e0382102d7b27 storage/image/b8/b8af7d0fbf094517781e0382102d7b27.jpg storage/video/b8/b8af7d0fbf094517781e0382102d7b27.240.mp4 … storage/video/b8/b8af7d0fbf094517781e0382102d7b27.720.mp4
Дополнительная иерархия в виде videoHashChar2 нужна, чтобы избежать тормозов с большим количеством файлов в одной директории.
Структура хранения файлов на главном и раздающем сервере одинаковая. Для удобства загрузки файлов на раздающие сервера они смонтированы на главный сервер через nfs по локальной сети.
Защита ссылок
Все ссылки закреплены за пользователем и имеют ограниченный срок жизни. Пример ссылок:
XXX.XXX.XXX.XXX/balancer/play-list/6875?ue=1440614576&uh=0cbd48e20dc2bf396a2eece00cd9ec2f XXX.XXX.XXX.XXX/balancer/image/6875.jpg?ue=1440614576&uh=0cbd48e20dc2bf396a2eece00cd9ec2f XXX.XXX.XXX.XXX/balancer/video/6875.480.mp4?ue=1440614576&uh=0cbd48e20dc2bf396a2eece00cd9ec2f XXX.XXX.XXX.XXX/balancer/play-list/<b>{videoId}</b>?ue=<b>{expires}</b>&uh=<b>{hash}</b>
Параметры:
videoId – идентификатор видео;
expires – время окончания жизни ссылки;
hash – хеш из параметров ссылки, данных пользователя и соли (videoId, expires, salt, ip, UserAgent, …).
Если проверка проходит успешно, то выбрасываю для nginx заголовок X-Accel-Redirect. Прямой доступ на видео закрыт директивой internal. Первоначально хотел использовать ngx_http_secure_link_module, но для гибкости
Главный сервер
Параметры:
- Hexa Xeon E5-2430v2, 6х2.50GHz, 4x 8TB SATA3 7.200 RPM, 48GB DDR3 ECC;
- CentOS Linux 6;
- Raid 10;
- Порт 1Gbit/s;
- Nginx 1.8 + php-fpm (php 5.6), mysql 5.5.
split_clients "${remote_addr}${request_time}${time_local}" $balance_g1_addr {
33% AAA.AAA.AAA.AAA;
33% BBB.BBB.BBB.BBB;
34% CCC.CCC.CCC.CCC;
}
split_clients "${remote_addr}${request_time}${time_local}" $balance_g2_addr {
33% DDD.DDD.DDD.DDD;
33% EEE.EEE.EEE.EEE;
34% FFF.FFF.FFF.FFF;
}
split_clients "${remote_addr}${request_time}${time_local}" $balance_g3_addr {
100% GGG.GGG.GGG.GGG;
}
server {
charset utf-8;
client_max_body_size 1024M;
listen XXX.XXX.XXX.XXX:80;
server_name XXX.XXX.XXX.XXX;
root /home/server/site/web;
index index.php;
access_log off;
error_log /var/log/nginx/servers_error.log;
location / {
try_files $uri $uri/ /index.php?$args;
}
location /storage {
root /home/server;
internal;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /home/server/site/web/$fastcgi_script_name;
fastcgi_pass unix:/tmp/server1-fpm.sock;
try_files $uri =404;
}
location ~ /\.(ht|svn|git) {
deny all;
}
location ~ /ds-g1/(.+)$ {
internal;
return 302 "http://$balance_g1_addr/$1?$args";
}
location ~ /ds-g2/(.+)$ {
internal;
return 302 "http://$balance_g2_addr/$1?$args";
}
location ~ /ds-g3/(.+)$ {
internal;
return 302 "http://$balance_g3_addr/1?$args";
}
}
Баланcировка между раздающими серверами в рамках группы реализована через модуль ngx_http_split_clients_module. Когда запрашивается видео, то на бэкенде определяет к какой группе принадлежит видео и выбрасывает заголовок X-Accel-Redirect.
Пример:
XXX.XXX.XXX.XXX/balancer/video/7190.720.mp4?ue=1440614576&uh=0cbd48e20dc2bf396a2eece00cd9ec2f
Если видео с id=7190 принадлежит к группе 2, то заголовок X-Accel-Redirect будет следующим:
/ds-g2/sv/7190.720.mp4?ue=1440614576&uh=0cbd48e20dc2bf396a2eece00cd9ec2f. Потом будет выбран сервер из группы 2 (например EEE.EEE.EEE.EEE) и отправлен редирект 302 Moved Temporarily на
EEE.EEE.EEE.EEE/sv/7190.720.mp4?ue=1440614576&uh=0cbd48e20dc2bf396a2eece00cd9ec2f.
В нашей конфигурации 3-и группы. Так как все раздающие сервера размером 2TB и портом 1Gbit/s, то с учетом разбивки имеем 6TB полезного места и суммарный порт 7GB. 1 и 2 группа — это суммарный объем 4TB и порт 6Gbit/s. 3 группа – это объем 2TB и порт 1Gbit/s.
3 группа особенная, в ней находятся самые непопулярные видео. Данная группа заполняется в полуавтоматическом режиме. Новые ролики распределяются только по первым двум группам, так как они потенциально являются популярными (по крайней мере первое время). Это сделано, чтобы по максимуму использовать место и порт.
Если не делать отдельную группу под непопулярные видео, то в других группах быстро закончится свободное место и при этом канал будет загружен не на 100%.
В группе может быть любое количество серверов. Полезный объем и максимальный размер порта определяется по самому слабому серверу в группе. Группы могут быть с разным объемом и портом.
Такой маленький объем раздающих серверов в 2TB связан с использованием 4x512GB SSD TLC. Эксперимент с 2x4TB SATA3 7,200 RPM закончился фиаско, так как на них смогли выжать только 0.3Gbit/s, при доступном порте 1Gbit/s.
Раздающий сервер
Параметры:
- Hexa Xeon E5-2430v2, 6х2.50GHz, 4 x 512GB SSD TLC, 48GB DDR3 ECC;
- CentOS Linux 6;
- Raid 0;
- Порт 1Gbit/s;
- Nginx 1.8 + php-fpm (php 5.6).
server {
listen 80;
root /home/user/site/web;
index index.php;
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /home/user/site/web$fastcgi_script_name;
fastcgi_pass unix:/tmp/upstream1-fpm.sock;
}
#image
location ~ ^/si/.+\.jpg$ {
rewrite .* /image.php?$args;
}
#video
location ~ ^/sv/.+\.(\d+)\.mp4$ {
rewrite .* /video.php?$args;
}
location ~ ^/image/.+\.jpg$ {
root /home/user/storage;
internal;
}
location ~ ^/video/.+\.mp4$ {
root /home/user/storage;
internal;
location ~ \.240\.mp4$ {
mp4;
mp4_buffer_size 1m;
mp4_max_buffer_size 10m;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
expires max;
directio 10m;
limit_rate 96k;
limit_rate_after 3m;
}
location ~ \.360\.mp4$ {
mp4;
mp4_buffer_size 4m;
mp4_max_buffer_size 10m;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
expires max;
directio 10m;
limit_rate 256k;
limit_rate_after 10m;
}
location ~ \.480\.mp4$ {
mp4;
mp4_buffer_size 8m;
mp4_max_buffer_size 20m;
limit_rate 512k;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
expires max;
directio 10m;
limit_rate_after 10m;
}
location ~ \.720\.mp4$ {
mp4;
mp4_buffer_size 20m;
mp4_max_buffer_size 40m;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
expires max;
directio 10m;
limit_rate 1024m;
limit_rate_after 10m;
}
}
}
Раздача видео реализована через модуль ngx_http_mp4_module для псевдо-стриминга. Чтобы его включить достаточно добавить директиву mp4.
Для каждого качества видео задана своя скорость отдачи limit_rate и размер первоночального куска, который будет отдаваться на максимальной скорости limit_rate_after. По коммерческой подписке nginx доступны mp4_limit_rate и mp4_limit_rate_after, которые задаются в секундах (это удобнее в разы, но бюджет на это не предусмотрен).
mp4_buffer_size — начальный размер буфера, используемого при обработке mp4-файлов.
mp4_max_buffer_size — в ходе обработки метаданных может понадобиться буфер большего размера. Его размер не может превышать указанного, иначе nginx вернёт серверную ошибку 500 (Internal Server Error).
sendfile, tcp_nopush, tcp_nodelay – одним словом ускоряет отдачу файлов.
directio – задание минимальный размер файла для включения режима чтение без обращение в кеш операционной системы.
expires – включение клиентское кеширование.
Пример плей-листа
XXX.XXX.XXX.XXX/balancer/play-list/7190?ue=1440614576&uh=0cbd48e20dc2bf396a2eece00cd9ec2f
Плей-лист возвращается в формате json:
{
"status": 1,
"data": {
"listVideo": {
"240": "http://XXX.XXX.XXX.XXX/balancer/video/7190.240.mp4?ue=1440614576&uh=0cbd48e20dc2bf396a2eece00cd9ec2f",
"360": "http://XXX.XXX.XXX.XXX/balancer/video/7190.360.mp4?ue=1440614576&uh=0cbd48e20dc2bf396a2eece00cd9ec2f",
"480": "http://XXX.XXX.XXX.XXX/balancer/video/7190.480.mp4?ue=1440614576&uh=0cbd48e20dc2bf396a2eece00cd9ec2f",
"720": "http://XXX.XXX.XXX.XXX/balancer/video/7190.720.mp4?ue=1440614576&uh=0cbd48e20dc2bf396a2eece00cd9ec2f"
},
"img": "http://XXX.XXX.XXX.XXX/balancer/image/7190.jpg?ue=1440614576&uh=0cbd48e20dc2bf396a2eece00cd9ec2f"
}
}
Ссылки
Cтриминг видео в «Одноклассниках» — www.highload.ru/2014/abstracts/1636.html
Видеохостинг своими руками — habrahabr.ru/post/111249
ffmpeg — www.ffmpeg.org
MP4Box — gpac.sourceforge.net
ngx_http_mp4_module — nginx.org/ru/docs/http/ngx_http_mp4_module.html
ngx_http_split_clients_module — nginx.org/ru/docs/http/ngx_http_split_clients_module.html
Отдача файлов с помощью nginx — ruhighload.com/index.php/2009/10/31/nginx-dlya-otdaci-failov
Комментарии (108)
FreeLSD
01.09.2015 16:48А где нашли такие широкие каналы?
esc
01.09.2015 17:23+1А сейчас разве не любой крупный ДЦ в прайсах содержит 10G порты с каналом?
FreeLSD
01.09.2015 17:47Интересна цена вопроса и можно ли ввязываться в межоператорские разборки на таких объемах отдаваемого трафика.
esc
01.09.2015 18:057 Gbit это такая мелочь, что в разборки вы точно не втянетесь. В моем случае, операраторы начали шевелиться, когда трафик перевалил за 150 внутри Украины.
А цена вопроса разная может быть. 7Гбит скорее всего будет по прайсу. С текущими скачками курсов скложно сказать сколько будет, сильно зависит от размещения и направления трафика.
От 100Г внутри страны, думаю, можно и бесплатное размещение обсуждать. Хотя, смотря какие перспективы, может и с 50 уже можно;)prodex
01.09.2015 19:46Специально искали сервера с гарантированным и безлимитным портом 1Gbits/s, а не шаред. Поэтому цена фиксированная за месяц.
DjOnline
01.09.2015 19:51+2Внутри какой страны?
esc
02.09.2015 11:59Внутри одной. Тогда вы будете интересны локальным операторам. Если трафик распределяется на несколько стран, возможно потребуются большие объемы.
DjOnline
19.09.2015 13:01Я помню такое было 15 лет назад, когда Masterhost платил за трафик для крупногенерящих проектов.
Сейчас разве кто-то так делает? Предлагает бесплатное размещение то есть бесплатные стойки + канал? Есть пример тех, кто это использует, в России?
prodex
01.09.2015 19:44Этот вариант просчитывали, но он экономически не рентабельный + маштабировать сложнее. Когда нам нужно 7Gbit/s, то зачем платить за 10Gbit/s? А если потребуется 12Gbit/s, то брать два по 10Gbit/s тоже не вариант.
erlyvideo
01.09.2015 19:48есть хостеры, готовые очень вменяемо расширять полосу внутри 10-гигабитного порта.
prodex
01.09.2015 20:39Как понять расширить? Вы рассматриваете вариант, когда сервер с шаред портом, а не с гарантированным?
erlyvideo
01.09.2015 20:56Да вы всё упираетесь в понятия шаред, гарантированный, хотя это условности.
У хостера есть какой-то объём связности, т.е. его собственный аплинк. Сколько он из этого аплинка вам готов зарезервировать, столько вы и получите. Какая при этом скорость подключения вашего сервера к свитчу — это уже отдельное дело, но удобно иметь 10-гигабитное подключение, при котором хостер берет не за все 10 гигабит, а за меньшую сумму.prodex
01.09.2015 21:06Я вас понял, но такой сценарий мало вероятен. У них есть сервера с шаред портом 10Gbit/s из которых 1-3Gbit/s будут гарантированными. Но это тоже все по фиксированному прайсу, где свой размер гарантированного порта не протолкнуть.
esc
02.09.2015 12:02Очень просто, 10G при небольшом к-ве серверов будет существенно дешевле, чем ферма гигабитных. Просто за счет стоимости самого железа. Надо только поискать ДЦ, которые делают спец. позиции в прайсах для трафикогенераторов.
prodex
02.09.2015 13:16К сожалению нет. Сервер с 10Gbit и SSD (на мой объем видео) не будет существенно дешевле. Да и не нужно забывать про отказоустойчивость.
ИМХО 10 серверов по 1Gbit мне кажется надежнее, чем один с портом 10Gbit.
Конечно я могу ошибать, но если вы знаете где есть такие сервера недорого, то дайте ссылку. Я буду очень признателен.esc
02.09.2015 13:25Кажется надежнее, на самом деле 10 серверов это менее надежно, чем 2-3. Ссылку на fdcservers я ниже уже бросал, в принципе подойдет любой крупный хостер, у которого в прайсах есть 10Г порты. Надо только ему написать, а не выбирать из стандартных вариантов (те как раз не всегда оптимальны).
kevit
08.09.2015 17:22а сколько по-вашему недорого за честных 10гбит интернета/россии?
esc
15.09.2015 19:17Больше 500 баксов в месяц я думаю рассматривать нет смысла. Тем более, если трафик не на рунет в основном (тогда за эти деньги уже с сервером можно взять).
kevit
16.09.2015 07:38микс из когента с харрикейном у fdcservers)) с ценой 0.05 доллара за мегабит:))) но самая большая проблема даже не в этом, а в том что часть ваших пользователей будет постоянно сидеть в congested на россию
kevit
16.09.2015 07:41там ниже писали оценку, в 0.6 за мегабит на объеме я еще могу поверить, 0.05 вы примерно можете представить во сколько раз больше продает хостер к своей емкости портов
esc
17.09.2015 02:40Российские хостеры в основном не верят в то, что цены на порты и трафик давно снизились. Потому, даже с учетом кризиса, многие продолжают сидеть в Европе и/или договариваться с точками обмена.
erlyvideo
01.09.2015 18:19да немало таких предложений.
FreeLSD
01.09.2015 18:23Предложение-то немало, мне интересно по какой цене покупают такие каналы.
Честные 7 гигабит меньше 350.000 не должны стоить. Вот и интересно кто где почем беретerlyvideo
01.09.2015 19:36ох, больную тему вы затронули.
Ваша цена (по сегодняшнему курсу евро) — это хорошее, приличное и качественное предложение. На канале, который можно купить за такие деньги видео обычно не лагает и всё работает.
Однако есть хостеры, которые не моргнув глазом предлагают чуть ли не за 50 тыс рублей десятку в месяц. Очень тяжело объяснить клиентам таких хостеров, что им продали порт, а не канал до куда-то.
ULP
01.09.2015 20:28да, 350тыр это стоит. если это чистая генерация, то в Билайне, Мегафоне, РТКОмме или прочих операторах ШПД можно вероятно сделать тысяч за 70 если коэффициент будет 1/20 и более.
CMHungry
01.09.2015 21:46не факт. у ШПД с отдачей и так все очень плотно. Скорее просто у магистрала можно обсудить цену на соотношение.
CMHungry
01.09.2015 21:45где, в Москве, в Питере, в Хабаровске? Связность зарубежная, отечественная, запад или китай и иже с ним?
esc
02.09.2015 12:14От размещения и связности очень сильно зависит цена. Так, что сначала стоит именно с размещением и направлениями трафика определиться. Если трафик планируется на одну страну или группу стран, то стоит помониторить покрытие этих стран точками обмена. Отдача трафика в точки обмена будет гораздо дешевле, чем просто канал. В том числе и из коммерческих дата-центров. Проблема только в том, что надо индивидуально обсуждать.
BasilioCat
02.09.2015 14:12Если вы, скажем, берете 150 гигабит, договорившись на некоторую цену, а потом вдруг передумали и хотите взять 50. Так вам за 50 предложат заплатить столько же, что и за 150. Ну а 7 — это в розницу, тут примерно ценник понятен
При больших объемах лучше договариваться о каналах до точек обмена трафиком, и непосредственно о стыках с магистралами и крупными провайдерами, отдавая во внешний канал только то, что нельзя спихнуть остальным
xeioex
01.09.2015 17:30+5> sendfile, tcp_nopush, tcp_nodelay – одним словом ускоряет отдачу файлов.
> directio – задание минимальный размер файла для включения режима чтение без обращение в кеш операционной системы.
А вы уверены что ваша конфигурация работает так как вы ожидаете?
читаем документацию и видим:
Enables the use of the O_DIRECT flag (FreeBSD, Linux),…
The directive automatically disables (0.7.15) the use of sendfile for a given request. It can be useful for serving large files:
directio 4m;
or when using aio on Linux.
Для кросспроверки читаем маны:
man 2 open
O_DIRECT (Since Linux 2.4.10)
Try to minimize cache effects of the I/O to and from this file. In general this will degrade performance, but it is
useful in special situations, such as when applications do their own caching.
Для раздачи файлов и особенно больших nginx полагается на кеш операционной системы, так как она в любом случае кеширует файлы в памяти. В противном случае кеширование будет выполнено в двух местах что не оптимально. Т.е. вы мало того что указываете конфликтующие параметры, так в случае с directio деградируете производительность.
> одним словом ускоряет отдачу файлов.
слишком упрощенный взгляд на вещи (особенно если производительность для вас в приоритете), я бы рекомендовал читать документацию внимательно (благо она лаконичная) и не копировать конфигурации не вникая.prodex
01.09.2015 21:49С кешем операционной системы вышла заминка. Тогда странно, почему nginx рекомендует использовать directio для больших файлов (nginx: directio).
erlyvideo
01.09.2015 22:13до 10 гигабит это всё уже не особо актуально. От directio в том виде, в котором оно есть в линуксе больше проблем, чем решений.
В других юниксах типа фрибсд тоже не сильно легче.
xeioex
01.09.2015 22:35Изначальная задача directio в том что бы большие, но редкие файлы не вымывали небольшие и часто запрашиваемые файлы из кеша операционной системы.
>Тогда странно, почему nginx рекомендует использовать directio для больших файлов (nginx: directio).
перечитал документацию несколько раз и так и не увидел рекомендации. все что там указано это то что включается указанный флаг операционной системы. Итоговое поведение зависит уже от операционной системы и как справедливо заметили ниже, на линуксе от directio больше проблем чем пользы.
erlyvideo
01.09.2015 23:25Может всё таки скорее для того, что бы софт сам мог управлять кешем?
Т.е. не большие vs маленькие, а просто перенос знания о полезности кеша в софт? Это же вроде оракл коммитил в линукс.xeioex
01.09.2015 23:32+1Да, это ровно то что указано в мане "...but it is useful in special situations, such as when applications do their own caching", но я говорил про директиву nginx'а directio, а не флаг O_DIRECT.
sebres
02.09.2015 11:06+1Вам xeioex практически все верно написал… по крайней мере исходя из вашего сценария.
При работе с такими большими объемами (гарантированно не помещающимися в кэш) directio только увеличит нагрузку на дисковую систему, т.к. в таком случае имеем множественные блокировки (посредством дискового IO), поэтому лучше вообще использовать поток пулов. Подробнее отличная статья на хабре от VBart.prodex
02.09.2015 12:19Директиву directio профиксил, но эффект на 1 гигабитном серваке не сильно заметен, наверное для 10 гигабитного разница была бы значительной.
С потоком пулов давольно интересно, протестирую на одной группе.
esc
01.09.2015 17:34+1Хм, вы держите ферму серверов ради 7 Гбит? Еще и 48 ГБ памяти… Откройте для себя 10Г сетевые и правильно настройке aio+directio, как минимум, будете одного с такого сервера десятку раздавать, а не пару гигабит.
На таких объемах неплохо себя покажут гибридные сервера, где допустим будет пара 4ТБ винтов и 4 ssd + двухпортовая 10Г карта. 2 таких сервера вам запросто 40Г увалят, если каналы будут (и запросов достаточно). (2 скорее для отказоустойчивости)
Скриптами популярные файлы просто на ssd копируйте с винтов и отдаете всегда с ssd, если они там есть.prodex
01.09.2015 19:41Серверы с гарантированным портом 1Gbit/s обходятся около 200$. Находятся в Англии.
>Еще и 48 ГБ памяти…
С меньшим объемом не было, иначе бы взяли.
>Откройте для себя 10Г сетевые
Этот вариант просчитывали, но он экономически не рентабельный + маштабировать сложнее. Когда нам нужно 7Gbit/s, то зачем платить за 10Gbit/s? А если потребуется 12Gbit/s, то брать два по 10Gbit/s тоже не вариант.
В данной схеме выход 1-2 серверов из строя не обрушит всю систему, просто видео будет отдаваться медленее, но будет работать.esc
02.09.2015 12:08Ну я понял, что у вас просто не самое подходящее предложение от хостера. Тем не менее, стоит поискать в Европе предложения специально для трафикогенераторов. fdcservers.net мне регулярно спамит какими-то «эксклюзивными» конфигурациями для серверов с 1-2 10Г портами. Хотя на сайте у них хлам какой-то, но полагаю что предложениями с сайта их возможности совсем не ограничиваются. Ну или лизвеб какой-то.
Канал там честный, нужно только аккуратно к конфигурации железа относиться, они любят впарить старый хлам тем, кто не обращает внимание на платформу.prodex
02.09.2015 12:25У fdcservers.net ценник c учетом SSD получается значительно выше.
esc
02.09.2015 12:31У них сотни предложений по серверам. В сайте практически ничего нет. За 5 минут выкопал в почте такое:
2U Dell FS12-TY Dual Xeon L5520--12bay
64GB RAM
12 x 2TB or 12 x 120Gb SSD
10Gbps unmetered $699/mon
Но думаю, что если с ними списаться, то получится за подобные деньги взять более свежие Ксеоны, которые и 20 прокачают.
NickyX3
04.09.2015 15:05Скриптами популярные файлы просто на ssd копируйте с винтов и отдаете всегда с ssd, если они там есть.
При таком объеме памяти скриптами можно копировать особо популярные вообще в память применив к примеру tmpfsesc
04.09.2015 15:14Ну ssd 2ТБ, а памяти всего 48Г. Хотя, можно конечно и туда копировать. У нас суперкеши, которые по 80Г раздают, так и работают. 256ГБ памяти выделено под самый горячий кэш и на него под 40Г и приходится.
NickyX3
04.09.2015 15:21256ГБ памяти выделено
Да у автора мне кажется объемы поменьше. Когда я работал над (закрытом три года назад) другим проектом мы сливали до десятка роликов в tmpfs (которые просто чекались там через try) объемом 1 гиг всего. На сервер с 8 гигами памяти
BasilioCat
01.09.2015 18:10+2На нормальных (но не топовых) SSD вполне реально отдавать 40 гбит с одного сервера. Мешать жесткие диски и SSD на одном сервере мне думается нет смысла — корзин не хватит.
Мне не понятно только, зачем нужен псевдостримминг, который был придуман только как костыль для флэша, который блокирует заголовки Byte-range. Сейчас любой телефон умеет HTML5 video — можно просто отдавать видео как файлы. Если хочется странного, то в дополнение можно отдавать видео в HLS/HDS, на лету это умеет делать Nginx+, Wowza, FMS, Erlyvideo/Flussonicprodex
01.09.2015 20:27>На нормальных (но не топовых) SSD вполне реально отдавать 40 гбит с одного сервера
Отдать можно, но гарантированный и безлимитный порт в 10Gbit/s уже не рентабелен.
>Сейчас любой телефон умеет HTML5 video — можно просто отдавать видео как файлы.
Тогда не будет возможности перемотки (без полного скачивания ролика).
На счет HLS думал, но конвертация налету кажется плохой затеей. Нужно протестировать нагрузку. А хранить одновременно mp4 и HLS накладно. Да и мобильного трафика не так много, как хотелось бы.BasilioCat
01.09.2015 20:5240 Гбит — ну вопрос в объемах… 10Гб порты уже есть даже для арендованных серверов в Московских ДЦ, ну а цена — вопрос рентабельности проекта. Обычно 10 шт портов по 1Гбит стоят дороже. У одного видеохостинга была года полтора назад полоса в 180 гбит/с, ну и одноклассники тут озвучивали свои объемы трафика.
HTML5 video с файлом обработанным mp4box перематывается нормально и без скачивания контента — проверьте с телефона сниффером на сервере
HLS включает в себя смену контейнера на mpeg ts — по опыту моего коллеги, написавшего модуль для nginx, это не сильно накладная операция. Но практически все устройства, умеющие HLS, умеют и HTML5 video, так что особой необходимости для vod нет, только для live-потоков — для них нет альтернативы.erlyvideo
01.09.2015 21:00тем не менее смена HLS на mp4 на хостинге повышает расход трафика на от 30% до 100%
Это присходит по разным причинам: от промежуточных проксей до глюкавых реализаций плееров.BasilioCat
01.09.2015 21:06Прокси — это да. В целом HLS/HDS для них в первую очередь и придуман. А какие клиенты кривые — да еще чтоб давать такой процент?
BasilioCat
01.09.2015 21:09+1Собственно, псевдостримминг тоже не совсем решение для проксей — плеер обычно спрашивает не кусками, а от нужной позиции (а то и с начала) и до конца файла, что точно также дает выкачивание файла проксей. А то и по нескольку раз с разными параметрами начала просмотра =(
erlyvideo
01.09.2015 22:14Конечно. Клиент поскипал несколько раз субтитры с запросом ?from= а прокси сервер докачал один файл 8 раз.
prodex
01.09.2015 21:31+1>Сейчас любой телефон умеет HTML5 video — можно просто отдавать видео как файлы.
Тогда не будет возможности перемотки (без полного скачивания ролика).HTML5 video с файлом обработанным mp4box перематывается нормально и без скачивания контента — проверьте с телефона сниффером на сервере
Мобильного трафика меньше половины. А по десктопным браузерам встречаются еще те мамонты. Поэтому использовать на всех клиентах HTML5 Video пока не получится.BasilioCat
01.09.2015 21:48Снимите статистику по юзерагентам из логов — вы удивитесь сколько из них поддерживают HTML5 video / h264. Fallback на флэш для ie6 можно реализовать отдельно — благо файлы одни и те же для псевдостимминга и html5 video
erlyvideo
01.09.2015 20:59да не, конвертация на лету это не страшно =) Наш Flussonic без проблем 9-10 гигабит отдает с генерацией HLS/HDS на лету из mp4.
TheRaven
02.09.2015 10:11+1Для отдачи mp4 в виде HLS\HDS\DASH еще можно вот такую штуку использовать — github.com/kaltura/nginx-vod-module
BasilioCat
02.09.2015 13:46На первый взгляд весьма интересное решение, да еще и Open Source. Спасибо, очень ценная рекомендация!
esc
02.09.2015 12:37Псевдостриминг нужен для флеша. А флеш на данный момент безальтернативный проигрыватель видео с высоким разрешением и в высоком битрейте. Мы уже 2 года пытаемся отказаться от флеша, но приходится оставлять legacy версию т.к. html5 банально жрет больше ресурсов и видео тормозит на слабых компьютерах (которых немало). И это не проблема корявой реализации плеера, у ютуба история аналогичная.
Да, на i7 и наверное даже i3 разница неощутима, но в мире пока не у всех i7.BasilioCat
02.09.2015 13:15Flash содержит в себе вполне обычный декодер для h264, как и браузер для HTML5 video. Насколько я знаю, флэш умеет пропускать кадры, если процессор не справляется, и умеет ускорять декодирование на GPU и/или SSE3. Не тестировал декодеры браузеров, но мне смутно кажется, что они с этим должны справляться не хуже. Вы тестировали производительность декодирования одного и того же файла во флеше и средствами браузера?
Ну и флэш давным давно умеет HDS (это нативный для него формат), и не так давно HLS при помощи сторонних плагинов для проигрывателей (довольно кривая реализация на мой взгляд), что делает псевдостримминг слегка устаревшимesc
02.09.2015 13:22+2У флеша проигрыватель просто более оптимизирован, особенно полноэкранный. Наверное, потому что там реально полноэкранный режим, а не просто распахнутое на весь экран окно, как в случае html5. Хотя, возможно не только в этом дело. Факт — флеш на слабых машинах показывает себя гораздо лучше в данной задаче. Я это разумеется тестировал, более того, legacy плеер именно этой задаче и занимается — показывает те же файлы, что и html5, но более оптимально.
Касательно hds/hls, да, флеш это умеет. А html5 на десктопах — практически нет;)
mp4 + псевдостриминг это самый простой вариант. Не надо медиасерверов, не надо определять что там кто умеет принимать и т.д. Бесплатный штатный модуль к nginx и ваше видео доступно всегда и везде.
Да, стриминг поддерживает кое-какие фичи и позволяет сэкономить какой-то трафик в определнных случаях. Но сложность и стоимость внедрения сильно выше и часто это банально того не стоит.
Antex
01.09.2015 18:27+3ffmpeg может сам ставить moov в начало: -movflags faststart (правда, я не помню с какой это версии)
Как насечет перейти на hls/mpeg-dash? Например, nimble умеет хорошо «трансмуксить» налету из mp4 в hls и прочее.BasilioCat
01.09.2015 21:00Если я не путаю, то ffmpeg это делает вторым проходом, пересоздавая файл, что в целом от mp4box и qt-faststart не отличается.
HLS десктопом не поддерживается (кроме Safari по-моему), перепаковывать на лету умеет куча платного софта примерно в одной ценовой категории (до1000$ за серверную лицензию) — я писал чуть выше списокw7062c
02.09.2015 05:51+1На десктопе оно хорошо поддерживается сторонними плеерами — навскидку это JWPlayer и bitdash. Кроме того, можно на лету генерить MPEG-DASH, у которого нативная поддержка активно появляется на разных платформах, вплоть до телевизоров. Ну а по цене — Нимбл, например, бесплатен.
Antex
02.09.2015 13:30+2на десктопы и тв можно загонять видео в dash, а на мобилы в hls. Nimble все это умеет и он бесплатен.
itcoder
01.09.2015 23:06Ждем код демона на github.
А зачем через exec делать форки потоков, почему не взяли тот же supervosor? указав нужное количество потоков которые вычитывали очередь, по моему так было бы надежнее.prodex
02.09.2015 07:01+1Форк через exec со своей задачей тоже справляется. Если будет лагать, то посмотрю в сторону supervosor.
TimsTims
02.09.2015 08:52+1А вы уверены, что 7гбит вам хватает? Может вы как-раз и не растете и пользователи от вас уходят, потому-что у остальных тормозит?
Всё согласено систематической ошибки выжившего https://ru.m.wikipedia.org/wiki/Систематическая_ошибка_выжившего
И разве вам под рост проекта не нужны резервные мощности? Или вы уже поставили точку и роста не ожидаете?prodex
02.09.2015 12:39Мы отслеживаем статистику по сайту и статистику загруженности серверов. Динамика прироста после внедрения еще не изменилась, растем как раньше. Но при этом проблема с нерабочими видео решена. Теперь не страшно, если «партнер» удалит у себя видео или банально ляжет.
По примерной оценке размер видео был 4-5TB и максимальный порт в час пик около 5-7Gbit/s
Данные показатели рассчитывали для основных сайтов «партнеров». Сейчас начинаем загружать остальных, поэтому на подходе еще несколько серверов. Плюс с 1Gbit серверами, что мы их можем добавлять по мере необходимости.
Если суммарный канал будет более 20-30Gbit/s, то сделаю расчеты для серверов с портом 10Gbit/s.
Aquary
02.09.2015 09:33+1Интересный подход с группами — очень востребованный сценарий. Главная проблема — с приоритизацией и в последующим ранжированием видео между группами, создается определённый оверхед на все эти операции.
Обратите внимание на подход с балансировкой VOD между эдж-серверами, описанный в этой статье.
Здесь эджи сами подкачивают чанки по мере необходимости, а настройка параметров объёма и времени хранения даёт возможность избегать хранения неиспользуемых данных.
То есть вопрос выбора востребованных и популярных фильмов и роликов решается автоматически — зритель голосует просмотрами, непопулярное видео уходит в /dev/null, ориджин при этом раздаёт только востребованные файлы на эджи.
Кстати, выше BasilioCat верно заметил, что при раздаче через псевдостриминг плеер зачастую просто выкачивает ведь файл. Скорости сейчас хорошие и если зритель решил закрыть кино через 20 минут и пойти спать — к тому времени скачается весь файл целиком. Вот вам оверхед по трафику. В случае применения описанного подхода — подкачка нужных файлов и выставления параметров хранения, плюс использование чанков HLS или DASH — фрагменты непопулярного кино будут выкачиваться только в нужном для просмотра объеме.BasilioCat
02.09.2015 10:44Архитектура origin-edge себя оправдывает в некоторых случаях (список не полный):
— центральное (нераспределенное) хранилище
— малое количество контента, но большой трафик
При этом построение системы эджей, часть из которых отдает популярное видео с быстрых носителей, а часть (менее популярное) с медленных, а совсем непопулярное отдается вообще в ориджинов (нет смысла кэшировать) — довольно сложная задача, нужен интеллектуальный балансировщик запросов. Сейчас, со снижением стоимости SSD, уровень edge с жесткими дисками можно вообще говоря и пропустить, оставив один уровень, но проблему с маловостребованным контентом это не решает — на edge-cерверах он не нужен. Также, egde сервера будут хранить лишний объем файлов, если они занимаются только кэшированием, а подготовкой контента (mp4->HLS) занимается origin.
Если система раздает видео с серверов, где оно и хранится (распределенное хранилище), то такая система лучше масштабируется — просто добавляется очередная пачка серверов. Также сервера более универсальны — при отдаче файлов по HTTP процессор используется мало, но его можно использовать для перекодирования видео.Aquary
02.09.2015 16:07Если система раздает видео с серверов, где оно и хранится (распределенное хранилище), то такая система лучше масштабируется — просто добавляется очередная пачка серверов.
Всё это тоже правильно, но вы упускаете вариант, при котором зрители физически находятся далеко. Сервер в Москве, зритель на Камчатке — и можно скольо угодно ставить серверов в датацентре, но камчадалам от этого не легче. Тут помимо экономии трафика (а он там дорогой), вы экономите время загрузки. При таком раскладе эджи крайне нужны. Как их наполнять — тут да, варинты есть, конечно. Можно по описаной в статье схеме, можно просто копировать всё содержимое один раз и всё. Но вариант в любом случае живой, его нельзя сбрасывать со счетов.BasilioCat
02.09.2015 17:03Никто не мешает хранить какую-то часть контента (популярную в данном регионе) на удаленной площадке, а остальное тянуть с центральной. Пусть даже в режиме проксирования, если каналы позволяют. Если объем контента небольшой, так и полную копию можно хранить. А если большой, то толку от одного сервера с кэшом на 2Тб будет только для очень популярных файлов. Распределенное хранилище ничем не хуже кэша, а вот управление им гораздо более гибкое, чем LRU в nginx. Да и нет оверхеда на хранение потоков в HLS+HDS+plain
prodex
02.09.2015 12:50За статью спасибо.
Кстати, выше BasilioCat верно заметил, что при раздаче через псевдостриминг плеер зачастую просто выкачивает ведь файл.
Я думал, что это зависит от плеера. Что мешает плееру выкачать поток HLS полностью?erlyvideo
02.09.2015 12:52если это флеш-плеер, то это дело его автора. Если это не флеш-плеер, то мешает то, что так никто не делает.
prodex
02.09.2015 13:07Главная проблема — с приоритизацией и в последующим ранжированием видео между группами, создается определённый оверхед на все эти операции.
Если эдж-сервера заполнять динамически в зависимости от популярности видео в текущий момент, то согласен, что создается оверхед. В моем случае, видео закрепляется за одной группой, в которую входят эдж сервера. Поэтому видео записывается на эдж сервер один раз, и то по локальной сети в 1Gbit (чтобы не забивать внешний порт для раздачи).Aquary
02.09.2015 16:10Да, в вашем случае с локальной сетью это отлично работает. Просто только столкнётесь с необходимостью сделать географическое разнесение контента — надо будет что-то другое придымывать. Но такое возникает не у всех, конечно.
Invision70
02.09.2015 09:52Порноиндустрия прожорлива по трафику… )
esc
02.09.2015 12:03+1В порноиндустрии такими объемами уже давно не оперируют. Как минимум, на порядок больше.
ibKpoxa
А почему такой странный ключик для сплита?
split_clients "${remote_addr}${request_time}${time_local}"
Как мне кажется что тут большие шансы что при повторном просмотре видео клиента отправит на другой сервер, вместо ответа «Файл не изменен», т.к. время запроса будет другое.
prodex
Это не критично