php fastcgi_finish_request,PHP函数之fastcgi_finish_request

一、概念

fastcgi_finish_request函数主要是用来,将已经处理的数据返回给客户端,并结束请求,同时在后台继续处理fastcgi_finish_request函数后面的任务。格式如下:boolean fastcgi_finish_request ( void )

返回值

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

需要注意以下几点在运行完函数fastcgi_finish_request后,虽然结束了客户端的请求,但是仍然需要占用php-fpm进程处理后续任务,如果任务特别耗时,这样就会带来一个问题,php-fpm进程都被占用,当请求再次到来的时候,就会出现网关错误。

当以命令行的模式,是没法调用fastcgi_finish_request函数的。

在fastcgi_finish_request函数任务完成之前,会一直锁定session,这样会导致后续程序处理等待状态。幸运的是,针对这个问题是有办法解决的,即在耗时的任务之前,调用session_write_close函数,调用函数session_write_close后,仍然可以读取session,只是不能再对session进行修改或是新增操作。

在使用session_write_close函数之前,使用相同的header和cookie分别发起请求,结果如下

d4d529c3d9419f5d082df2a34bb9be0d.png

此时,可以看到有两个进程,占用着同一个session文件

a82ee7bbe8887a63497f0205654a7821.png

在使用session_write_close函数之后,使用相同的header和cookie分别发起请求,结果如下

771435b8cc4394f6e558db249ac86cd8.png

可以看出,因为开启了session,使用session_write_close函数之前,第二次请求被阻塞了,使用session_write_close函数之后就不会阻塞了。

程序如下:session_start();

$_SESSION['count'] += !isset($_SESSION['count']) ? 0 : 1;

echo 'A:curTime : ', date("Y-m-d H:i:s"), "\n";

//session_write_close();

var_dump(fastcgi_finish_request()); /* 响应完成, 关闭连接 */

/* 记录日志 */

sleep(20);

file_put_contents('log.txt', "B:curTime:". date("Y-m-d H:i:s") . "\n", FILE_APPEND);

二、使用

当PHP运行在FastCGI模式时,PHP 提供了一个名为fastcgi_finish_request的方法。该方法可以提高请求的处理速度,因为此函数能够在将数据返回给客户端并断开与客户端的连接后,继续完成需要执行的任务。听着是不是很抓狂啊!

先来搞个简单的例子试一下,比如在页面输出当前时间,5秒后记录日志。<?php

echo "hello world\n";

echo 'A:当前时间:', date("Y-m-d H:i:s"), "\n";

var_dump(fastcgi_finish_request()); /* 响应完成, 关闭连接 */

/* 记录日志 */

sleep(5);

file_put_contents('log.txt', "B:当前时间:". date("Y-m-d H:i:s") . "\n", FILE_APPEND);

0c1645f0c753af90995b825b904ac6cd.png

下面封装一个类,便于在项目中引入和使用,如下:class FastcigCallbk {

public static $callbacks = [];

public static $checkPass = false;

/**

* 禁止实例化

* FastcigCallbk constructor.

*/

private function __construct() {

}

/**

* 判断是否支持fastcgi

* @return bool

*/

public static function check() {

if (PHP_SAPI != 'fpm-fcgi' || ! function_exists('fastcgi_finish_request')) {

self::$checkPass = false;

}

self::$checkPass = true;

return self::$checkPass;

}

/**

* 新增

*

* @param \Closure $c

* @param null     $k

*/

public static function add(\Closure $c, $k = null) {

self::$checkPass || self::check();

if (! self::$checkPass) {

throw new ExceptionBiz(Errors::ERR_SYSTEM . ';当前不支持fastcgi_finish_request');

}

if ($k) {

self::$callbacks[$k] = $c;

} else {

self::$callbacks[] = $c;

}

}

/**

* 删除

*

* @param $k

*

* @return bool

*/

public static function del($k) {

if ( ! isset(self::$callbacks[$k])) {

return false;

}

unset(self::$callbacks[$k]);

return true;

}

/**

* 执行

*/

public static function run() {

$callbacks = self::$callbacks;

if (empty($callbacks) || empty(self::$checkPass)) {

return false;

}

fastcgi_finish_request();

try {

foreach ($callbacks as $c) {

$c();

}

} catch (\Exception $e) {

//处理异常

}

}

}

使用说明

调用如下:if (FastcigCallbk::check()) {

FastcigCallbk::add(function () use ($list) {

//需要异步处理的程序

});

} else {

//当不支持的时候

}

触发,以thinkphp为例,直接放到项目代码运行结束的时候,如下:

d496b159daf7feb3b4c4c76824c1d61a.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值