PHP + gzip: закрыть соединение и продолжить выполнение - PullRequest
5 голосов
/ 09 октября 2009

Я отвечаю за бэкэнд API, написанный на PHP, который в основном используется Flash-клиентом. Сейчас происходит следующее: клиент Flash выполняет вызов, серверная часть загружает необходимые данные, выполняет всю необходимую обработку и последующую обработку, ведение журнала и кэширование, а затем возвращает результат клиенту.

То, что я хотел бы, чтобы это произошло, - вернуть данные клиенту как можно скорее, закрыть соединение, а затем выполнить все то, что клиенту не нужно заботиться. Это может сделать API более гибким. Следуя предложениям здесь:

http://php.net/manual/en/features.connection-handling.php

на самом деле работает, за исключением того, что я должен отключить кодировку gzip, чтобы заставить это работать, что не очень практично. Мы используем mod_deflate в apache, поэтому решение, которое работает с этим, было бы идеальным, но я бы также рассмотрел другой метод для сжатия нашего контента, если это необходимо.

Это кажется как будто должен быть способ сообщить Apache: «Я отправил вам все данные, которые собираюсь отправить», но я не могу найти ничего подобного.

Для тех, кто интересуется, да, я могу сбросить результаты раньше, но клиент Flash не будет обрабатывать их, пока не будет закрыто соединение.

Ответы [ 5 ]

3 голосов
/ 09 октября 2009

Вы можете попробовать разбить его на две страницы.

На первой странице выполните необходимую обработку, затем загрузите вторую страницу с помощью curl и die ().

Это может привести к завершению и закрытию первой страницы, независимо от обработки второй страницы.

есть:

Страница 1:

<?php

// Do stuff

// Post or get second page...

// Send Data to client

die();
?>

Страница 2:

<?php

// Do other stuff....

?>

См. http://www.php.net/curl

0 голосов
/ 15 февраля 2012

Сегодня я также встречал этот случай, после нескольких тестов, я обнаружил, что этот способ работает:

Два шага:

  1. Убедитесь, что вывод php-скрипта не с кодировкой gzip, решение может быть использовано по этой ссылке :

    <IfModule mod_env.c>
    SetEnvIfNoCase Request_URI "\.php$" no-gzip dont-vary
    </IfModule>

Добавьте вышеперечисленное в .htaccess файл на веб-сайте prj, затем избегайте apache gzip автоматически.

  1. Как говорили некоторые люди в features.connection-handling.php,

    set_time_limit(0); 
    ignore_user_abort(true);    
    // buffer all upcoming output - make sure we care about compression: 
    if(!ob_start("ob_gzhandler")) 
        ob_start();         
    echo $stringToOutput;    
    // get the size of the output 
    $size = ob_get_length();    
    // send headers to tell the browser to close the connection    
    header("Content-Length: $size"); 
    header('Connection: close');    
    // flush all output 
    ob_end_flush(); 
    ob_flush(); 
    flush();    
    // close current session 
    if (session_id()) session_write_close(); //close connection
    
    // here, do what you want.
    
0 голосов
/ 04 апреля 2011
set_time_limit(0);
header("Connection: close");
header("Content-Length: " .(strlen($stream)+256));
ignore_user_abort(true);

echo $stream;
echo(str_repeat(' ',256));
@ob_flush();
@flush();
 @ob_end_flush();

your_long_long_long_long_function_here();

это скажет пользователю закрыть соединение, как только все $stream получено. но будьте осторожны, чтобы ничего не повторить, прежде чем header часть, которую вы знаете: p

если вы отправляете двоичные данные (swf), вам может потребоваться удалить «+256» и echo(str_repeat(' ',256));, но в этом случае код «может» завершиться ошибкой, если отправленные данные меньше 256 байтов.

0 голосов
/ 09 октября 2009

@Theo.T, так как система комментариев исказила чушь из моего кода, я выкладываю ее здесь:

Не повезло. Следующее распечатывает лишнее дерьмо и занимает полное время выполнения, чтобы закрыть соединение при использовании mod_deflate:

function sleepLongTime() { 
    print "you can't see this";
    sleep(30);
}
ob_end_clean();
register_shutdown_function('sleepLongTime');
header("Connection: close\r\n");
ignore_user_abort(true);
ob_start();
echo ('Text user will see');
ob_end_flush();
flush();
ob_end_clean();
die();
0 голосов
/ 09 октября 2009

Это своего рода хак, поместив код, который вы хотите выполнить после закрытия соединения, в методе обратного вызова, зарегистрированного через register_shutdown_function();

...