NGINX - PHP-FPM Служба поиска фильмов и дескриптор соединения

0

Я запускаю PHP-FPM 5.6 и Nginx 1.7.6.

Я обслуживаю фильмы Matroska/Mp4, используя файл PHP. Код: этот:

<?php
register_shutdown_function( 'shutdown' );

$request = 'movie.mp4';

header( 'X-Accel-Buffering: no' ); //avoid nginx buffering.
header( 'Content-type: video/mp4' );

if ( file_exists( $request ) )
{

    $fp = @fopen( $request, 'rb' );

    $size = filesize( $request ); // File size
    $length = $size; // Content length
    $start = 0; // Start byte
    $end = $size - 1; // End byte
    header( "Accept-Ranges: 0-$length" );
    if ( isset( $_SERVER['HTTP_RANGE'] ) )
    {

        $c_start = $start;
        $c_end = $end;

        list( , $range ) = explode( '=', $_SERVER['HTTP_RANGE'], 2 );
        if ( strpos( $range, ',' ) !== false )
        {
            header( 'HTTP/1.1 416 Requested Range Not Satisfiable' );
            header( "Content-Range: bytes $start-$end/$size" );
            exit;
        }
        if ( $range == '-' )
        {
            $c_start = $size - substr( $range, 1 );
        }
        else
        {
            $range = explode( '-', $range );
            $c_start = $range[0];
            $c_end = ( isset( $range[1] ) && is_numeric( $range[1] ) ) ? $range[1] : $size;
        }
        $c_end = ( $c_end > $end ) ? $end : $c_end;
        if ( $c_start > $c_end || $c_start > $size - 1 || $c_end >= $size )
        {
            header( 'HTTP/1.1 416 Requested Range Not Satisfiable' );
            header( "Content-Range: bytes $start-$end/$size" );
            exit;
        }
        $start = $c_start;
        $end = $c_end;
        $length = $end - $start + 1;
        fseek( $fp, $start );
        header( 'HTTP/1.1 206 Partial Content' );
    }

    header( "Content-Range: bytes $start-$end/$size" );
    header( "Content-Length: " . $length );
    ob_end_flush();


    $buffer = 1024 * 8;
    while ( ! feof( $fp ) && ClientConnected() && ( $p = ftell( $fp ) ) <= $end )
    {
        $response = stream_get_line( $fp, $buffer );
        echo $response;

    }

    fclose( $fp );
}

function ClientConnected()
{
    if ( connection_status() != CONNECTION_NORMAL || connection_aborted() )
    {
        return false;
    }

    return true;
}


function shutdown()
{
    //main cause of problems is that line
    //posix_kill( getmypid(), 9 );
}

Вы заметите, что вышеупомянутый скрипт поддерживает диапазоны Accept, чтобы пользователь мог искать фильм ! Эта функция работает отлично, а также сам фильм. Я могу посмотреть фильм с моего плеера, обратившись к нему без каких-либо проблем.

ПРОБЛЕМА

Проблема заключается в функции выключения. Вы можете спросить, почему я хочу использовать posix_kill и убить php pid.

У пользователя есть возможность выбрать несколько фильмов для просмотра в моем приложении. Пользователь имеет LIMIT для подключений, которые могут быть открыты на моем сервере. Это означает, что если у пользователя есть 1 доступный слот для подключения к серверу, он сможет открыть только один фильм одновременно.

По этой причине скажем, что пользователь в данный момент смотрит фильм, и он хочет, чтобы ZAP (изменить) текущий фильм на другой.

Он не сможет этого сделать, потому что старое соединение не закончится быстро, и pid останется открытым еще на несколько секунд.

POSIX_KILL Пояснение

Если мы раскомментируем строку //posix_kill вышеуказанного кода, пользователь не сможет увидеть какой-либо фильм вообще, потому что почему-то функция posix_kill переопределяет все вышеперечисленные заголовки, а nginx/php не отправляет заголовки, которые у меня есть в файле,

Однако, если я DISABLE HTTP SEEK и включите posix_kill, как описано, пользователь сможет смотреть фильмы, но он не сможет найти. Это происходит потому, что, когда у нас есть заголовок Accept-Ranges, игроки делают несколько запросов к фильму, прежде чем открывать его.

Так, например, игрок будет делать 2-3 запроса к этому файлу PHP, чтобы понять и идентифицировать поиск. Posix_kill, однако, быстро убьет эти pids, и игрок не сможет принять правильные заголовки.

Что мы хотим

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

PS. Вышеприведенный код с включенным posix_kill работает ОТЛИЧНО в режиме потокового вещания, поскольку мы не стремимся, чтобы игрок сделал только один запрос.

Надеюсь, ты меня понял

  • 0
    То, с чем вы имеете дело, звучит как идеальная работа для Mongrel2 и PHP через ZeroMQ. Если вам когда-нибудь удастся взглянуть на упомянутое, я могу заверить вас, что вы удивитесь, почему вы никогда не использовали его раньше. Во всяком случае, поскольку вы разобрались с проблемой - рассмотрите мой комментарий как что-то, чтобы удовлетворить любопытство, когда вы получите время.
Теги:
nginx
posix

2 ответа

1

Если у вас нет проблемы с безопасностью. Тогда используйте mp4-модуль nginx. Он работает как псевдо-потоковая передача для mp4. После этого вам не нужен php, чтобы искать фильм на любой части. Сам Nginx.

  • 0
    Нет, соединение должно проходить из файла php. Это потому, что я делаю аутентификацию, которую я не включил в приведенный выше код
0

Я решил проблему с fastcgi_finish_request();

Из руководства PHP:

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

Моя функция останова:

function shutdown()
{
    fastcgi_finish_request();
    posix_kill( getmypid(), 9 );
}

Ещё вопросы

Сообщество Overcoder
Наверх
Меню