fastcgi_finish_request

(PHP 5 >= 5.3.3, PHP 7)

fastcgi_finish_request冲刷(flush)所有响应的数据给客户端

说明

fastcgi_finish_request ( void ) : boolean

此函数冲刷(flush)所有响应的数据给客户端并结束请求。 这使得客户端结束连接后,需要大量时间运行的任务能够继续运行。

返回值

成功时返回 TRUE, 或者在失败时返回 FALSE

User Contributed Notes

marcelotpcruz at gmail dot com 12-Sep-2019 08:13
Here goes a workaround if you can't use fast cgi.
You'll need to replace echo with puts function everywhere:
<?php
   
function puts(){
        static
$init    = false;
       
$numargs = func_num_args();
       
$arg_list = func_get_args();
       
$string = '';
       
        if(
$numargs === 0)
            return;
        else if(
$numargs > 1)
           
$string = implode('', $arg_list);
        else
           
$string = $arg_list[0];
   
        if(
$init === false)
        {
           
// buffer all upcoming output - make sure we care about compression:
           
if(ob_start("ob_gzhandler")){
               
connsettings('compression', true);
                echo
'Yes compression';
            }else{
               
ob_start();
                echo
'No compression<br>';
            }
           
$init = true;
           
register_shutdown_function('puts', null, true);
        }
        echo
$string;
    }
    function
connsettings(/*$name, (optional)$val=$arg_list[1]*/){
        static
$settings= array();
       
$numargs        = func_num_args();
       
$arg_list        = func_get_args();
       
$name            = $arg_list[0];
       
        if(
$numargs === 1)
            return
$settings[$name] ?? null;
       
       
$oldVal            = $settings[$name] ?? null;
       
$settings[$name]= $arg_list[1];
   
        return
$oldVal;
    };
    function
connection_close(){
        if(!
headers_sent())//it may work without this verification when no compression but may lead to uncomplete data
       
{
           
set_time_limit(0);
           
ignore_user_abort(true);
           
// send headers to tell the browser to close the connection
           
ob_end_flush(); // Order here matter, it won't work if it goes after Content-Length
           
if(connsettings('compression') === false)
               
header("Content-Encoding: none");
           
header('Content-Length: ' . ob_get_length());
           
header('Connection: close');   
           
// flush all output
           
if(ob_get_level() > 0)
               
ob_flush();
           
flush();
        }
    }
//Usage
puts('Whatever you want to print...<br>');
puts('Some more<br>');
connection_close();

puts("It's never gonna be seen<br>");
echo
'Neither this';
?>
tuxrampage 04-Aug-2016 09:29
There are some pitfalls  you should be aware of when using this function.

The script will still occupy a FPM process after fastcgi_finish_request(). So using it excessively for long running tasks may occupy all your FPM threads up to pm.max_children. This will lead to gateway errors on the webserver.

Another important thing is session handling. Sessions are locked as long as they're active (see the documentation for session_write_close()). This means subsequent requests will block until the session is closed.

You should therefore call session_write_close() as soon as possible (even before fastcgi_finish_request()) to allow subsequent requests and a good user experience.

This also applies for all other locking techniques as flock or database locks for example. As long as a lock is active subsequent requests might bock.