apache — HTTP2 и продолжение выполнения PHP

При запуске PHP, и вы хотите, чтобы он немедленно возвратил HTML в браузер, закрыл соединение (ish) и затем продолжил обработку …

Следующее работает, когда соединение HTTP / 1.1, но не при использовании Apache 2.4.25, с mod_http2 включен, и у вас есть браузер, который поддерживает HTTP / 2 (например, Firefox 52 или Chrome 57).

Что происходит, Connection: close Заголовок не отправлен.

<?php

function http_connection_close($output_html = '') {

apache_setenv('no-gzip', 1); // Disable mod_gzip or mod_deflate

ignore_user_abort(true);

// Close session (if open)

while (ob_get_level() > 0) {
$output_html = ob_get_clean() . $output_html;
}

$output_html = str_pad($output_html, 1023); // Prompt server to send packet.
$output_html .= "\n"; // For when the client is using fgets()

header('Connection: close');
header('Content-Length: ' . strlen($output_html));

echo $output_html;

flush();

}

http_connection_close('<html>...</html>');

// Do stuff...

?>

Для похожих подходов к этой проблеме, см .:

  1. закрыть соединение рано
  2. Продолжить обработку после закрытия соединения
  3. Продолжить php скрипт после закрытия соединения

И почему connection заголовок удален, документация для nghttp2 библиотека (как используется Apache) заявляет:

https://github.com/nghttp2/nghttp2/blob/master/doc/programmers-guide.rst

HTTP/2 prohibits connection-specific header fields. The
following header fields must not appear: "Connection"...

Так что, если мы не можем сказать браузеру закрыть соединение через этот заголовок, как нам заставить это работать?

Или есть другой способ сообщить браузеру, что у него есть все для ответа HTML, и что он не должен продолжать ждать поступления новых данных.

1

Решение

Как вернуть HTTP-ответ пользователю и возобновить обработку PHP

Этот ответ работает только тогда, когда веб-сервер общается с PHP через FastCGI протокол.

Чтобы отправить ответ пользователю (веб-сервер) и возобновить обработку в фоновом режиме, без участия вызовов ОС, вызовите fastcgi_finish_request() функция.

Пример:

<?php

echo '<h1>This is a heading</h1>'; // Output sent

fastcgi_finish_request(); // "Hang up" with web-server, the user receives what was echoed

while(true)
{
// Do a long task here
// while(true) is used to indicate this might be a long-running piece of code
}

На что обращать внимание

  • Даже если пользователь получает вывод, php-fpm дочерний процесс будет занят и не может принимать новые запросы, пока они не закончили с обработкой этой длительной задачи.

Если все доступно php-fpm дочерние процессы заняты, тогда ваши пользователи будут испытывать зависание страницы. Используйте с осторожностью.

nginx а также apache оба сервера знают, как бороться с FastCGI протокол, поэтому не должно быть никаких требований по обмену apache сервер для nginx,

1

Другие решения

Вы можете обслуживать свои медленные PHP-скрипты через HTTP / 1.1, используя специальный поддомен.

Все, что вам нужно сделать, это установить второй VirtualHost, который отвечает HTTP / 1.1, используя директиву Apache Protocols: https://httpd.apache.org/docs/2.4/en/mod/core.html#protocols

Большим преимуществом этой техники является то, что ваши медленные сценарии могут отправлять некоторые данные в браузер задолго до того, как все остальное было отправлено через поток HTTP / 2.

1

По вопросам рекламы [email protected]