Раздача Видео. Пока: Nginx Или Php?

Хочу поделиться своим небольшим опытом реализации распространения видеоконтента.



Так

Есть сервис по распространению видеоконтента смотреть (т.е.

скачивание не предусмотрено).

При этом весь контент разделен на 2 категории: 1 — дается целиком (весь файл)/пауза, перемотка вперед и назад; 2 - предоставляется как один «виртуальный файл» вида [конец первого файла]+[определенное количество полных файлов]+[начало последнего файла].

Формат — mpegts, каждый набор кодируется одинаково, поэтому части можно просто склеить.

Эти две категории логически различны (совершенно разные вещи), имеют явно разные URI и физически расположены в разных местах.



Как первоначально предлагалось

Комбинация Nginx+apache. Первая категория — банальная раздача контента в nginx с небольшой настройкой.

Вторая часть выполняется через скрипт apache-php с использованием цикла.

  
  
  
   

while(!feof($fp)){ .

echo fread($fp, $buf) .

}

где $fp — указатель на файл, где функция fseek() выполняется там, где это необходимо.



Что мне не понравилось

Как оказалось, nginx не очень подходит для раздачи статических файлов с большим количеством запросов диапазона байт (а именно это те запросы, которые в основном поступают при просмотре онлайн).

Невозможно использовать AIO для обслуживания таких запросов.

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

Задавать большое количество буферов бесполезно — это просто трата памяти.

Я попробовал последнюю версию nginx (на данный момент 1.12.2), и --with-file-aio, и --with-threads, и еще много чего.

Никакого эффекта я не получил.

Ну, ссылка «echo fread()» в PHP тоже весьма сомнительна.

Вывод fread идёт в промежуточный буфер php и соответственно скрипт потребляет памяти не меньше этого буфера.

Если читать файл небольшими кусочками, увеличивается нагрузка на процессор и снижается скорость загрузки.

Если читать большими кусками, то на каждый запрос тратится слишком много памяти.



Что произошло в конце

Ну, во-первых, я отказался от Apache. Вместо этого php5-fpm. Это дало существенный прирост производительности (скорости отклика) + снижение потребления памяти.



Первая категория

контент, ради эксперимента решил попробовать отдать его вместе со своим сценарием.

В нгинксе:

location ~* /media/.

*\.

* { fastcgi_pass unix:/var/run/php5-fpm.sock; include /etc/nginx/sites-available/fastcgi_params; fastcgi_param SCRIPT_FILENAME /var/www/m_download.php; root /var/www; send_timeout 1h; }

Я не буду перечислять m_download.php полностью.

Основной функционал:

fpassthru($fd);

где $fd — указатель на файл.

Сначала, конечно, нужно разобрать заголовок HTTP_RANGE, открыть файл и установить в нем смещение.

fpassthru() возвращает файл «от текущего до конца».

В данной ситуации это было вполне уместно.

Все игроки играют правильно.

К моему великому удивлению, именно этот метод подачи дал мне нужный мне результат. Очереди на диск нет (точнее используется системный, но с моим SAS-3 12Гб/сек и жду<10ms it’s generally good).

Accordingly, there is no waiting for the request to be processed. The file upload speed (if downloaded) is about 250 Mbit/s. The “brakes” for clients have completely disappeared. В то же время использование памяти значительно уменьшилось, следовательно, больше осталось для файлового кэша.

Сам скрипт при выполнении потребляет около 0,5 МБ собственной памяти.

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



Вторая категория

(вот тут нужно собрать воедино несколько кусков разных файлов) тоже изменилось.

Я отказался от ссылки «echo fread()».

К сожалению, в PHP нет функции прямого вывода произвольного фрагмента файла.

fpassthru() не имеет параметра «сколько выводить», он всегда выводит «до конца».

Я попытался вызвать систему dd с помощью passthru().

Те.

:

passthru('/bin/dd status=none if='.

$fffilename.' iflag="skip_bytes,count_bytes" skip='.

$ffseek.' count='.

$buf_size);

И.

о чудо! Потребление памяти скриптом чуть больше 0,5 Мб, размер буфера можно установить любой (на память это не влияет).

Скорость отдачи (с буфером 4 МБ)… свистит (те же 250 Мбит/с).

Вот история.

В результате нам пришлось прекратить распространение контента, используя только nginx. Он используется, но только для перенаправления запросов на php5-fpm. Короче говоря, мое ИМХО: nginx хорошо рендерит статические файлы, но плохо читает с диска.

Никогда бы не подумал, что распространение файлов через PHP-скрипт может быть более эффективным.

Ну и добавлю, что искал какой-нибудь httpd с AIO для запросов диапазона байтов «из коробки».

Вроде Lighttpd версии 2 это умеет, но версия пока нестабильная.

Больше ничего подходящего не нашел.

Теги: #Nginx #php #обмен файлами

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.