HTTP2 并继续 PHP 执行
HTTP2 and continuing PHP execution
当运行PHP,而你想让它立即returnHTML到浏览器,关闭连接(ish),然后继续处理.. .
以下内容在连接为 HTTP/1.1 时有效,但在使用 Apache 2.4.25
、启用 mod_http2
并且您的浏览器支持 HTTP/2(例如 Firefox 52 或 Chrome 57)。
没有发送 Connection: close
header。
<?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...
?>
有关此问题的类似方法,请参阅:
- close a connection early
- Continue processing after closing connection
- Continue php script after connection close
关于 connection
header 被删除的原因,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"...
所以如果我们不能通过这个 header 告诉浏览器关闭连接,我们如何让它工作?
或者是否有另一种方式告诉浏览器它拥有 HTML 响应的所有内容,并且它不应该继续等待更多数据到达。
如何return HTTP 响应用户并恢复PHP 处理
此答案仅在网络服务器通过 FastCGI
协议与 PHP 通信时有效。
要向用户(Web 服务器)发送回复并在后台恢复处理,而不涉及 OS 调用,请调用 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
.
您可以使用特殊的子域通过 HTTP/1.1 为您的慢速 PHP 脚本提供服务。
您需要做的就是使用 Apache 的协议指令设置第二个响应 HTTP/1.1 的 VirtualHost:https://httpd.apache.org/docs/2.4/en/mod/core.html#protocols
这项技术的最大优势在于,您的慢速脚本可以在其他所有内容通过 HTTP/2 流发送很久之后向浏览器发送一些数据。
当运行PHP,而你想让它立即returnHTML到浏览器,关闭连接(ish),然后继续处理.. .
以下内容在连接为 HTTP/1.1 时有效,但在使用 Apache 2.4.25
、启用 mod_http2
并且您的浏览器支持 HTTP/2(例如 Firefox 52 或 Chrome 57)。
没有发送 Connection: close
header。
<?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...
?>
有关此问题的类似方法,请参阅:
- close a connection early
- Continue processing after closing connection
- Continue php script after connection close
关于 connection
header 被删除的原因,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"...
所以如果我们不能通过这个 header 告诉浏览器关闭连接,我们如何让它工作?
或者是否有另一种方式告诉浏览器它拥有 HTML 响应的所有内容,并且它不应该继续等待更多数据到达。
如何return HTTP 响应用户并恢复PHP 处理
此答案仅在网络服务器通过 FastCGI
协议与 PHP 通信时有效。
要向用户(Web 服务器)发送回复并在后台恢复处理,而不涉及 OS 调用,请调用 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
.
您可以使用特殊的子域通过 HTTP/1.1 为您的慢速 PHP 脚本提供服务。
您需要做的就是使用 Apache 的协议指令设置第二个响应 HTTP/1.1 的 VirtualHost:https://httpd.apache.org/docs/2.4/en/mod/core.html#protocols
这项技术的最大优势在于,您的慢速脚本可以在其他所有内容通过 HTTP/2 流发送很久之后向浏览器发送一些数据。