利用fastcgi_finish_request函数提高响应速度

当php运行在FastCGI模式时,PHP FPM提供了一个名为fastcgi_finish_request()的函数。按照文档上的说法,此函数可以提高请求的处理速度。我们业务中经常遇到这样的场景:比如生成文件较大的excel ,非常耗时,有可能需要5到30妙的时间,甚至更长的时间导致php超出最大执行时间等。另外一个就是体验问题,用户需要长时间的等待响应的完毕,体验较差。


类似的场景还有:

1、需要处理大的文件

2、发送邮件或短信,尤其是需要循环发送邮件通知等

3、调用远程耗时的api等

4、记录日志等


遇到以上这几种情况时,并且你的php是运行在FPM环境下时,就可以使用fastcgi_finish_request()函数了。


fastcgi_finish_request()函数的作用:

调用该函数的时候, 会发送响应给浏览器, 关闭连接。但是服务端的php进程还是在一直运行的。这样就达到了两个目录目的,有点类似于异步任务。

1、响应快:比如发送邮件需要3秒时间,但用户无感知,1妙之内就告诉用户发送邮件完毕。

2、耗时任务后台执行:浏览器响应结束了,用户可以做其他的事情。后台进程默默的执行发送邮件等任务。


上个效果动图:

233.gif

经过上面gif动图中的演示,我们达到了目的:

1、很快的响应,1毫米之内,浏览器响应结束。

2、后台任务,注意右侧上方的日志,每秒输出一个时间戳。


上个代码demo示例:

echo '输出给客户端的内容'; //会输出

fastcgi_finish_request();

//set_time_limit(0); //如果后面的任务耗时很长,可以设置为php执行时间没有时间限制。自行看情况是否选择添加该行代码

//ini_set('memory_limit','-1'); //php使用内存不受限制。自行看情况是否选择添加该行代码

sleep(1);

echo '放心吧,这里的内容并不会输出';  //不会输出

file_put_contents('log.txt', '这是客户端响应结束后,服务器段脚本继续执行后生成');

运行该代码,你会发现客户端输出上面一句话,fastcgi_finish_request()下面的内容并没有输出,但是却生成了文件,这说明了调用了fastcgi_finish_request()函数后,客户端响应就已经结束,但与此同时服务端的php代码却仍然在继续运行。这在一定程度上提高了响应速度,也提升了用户体验,也算是实现了一个简单的异步功能。


另外, 从代码的可移植性以及兼容性来讲的话, 可以在代码中附上如下代码(兼容非php-fpm)

if (!function_exists("fastcgi_finish_request")) 
{
      function fastcgi_finish_request()  
      {
          //do some thing
      }
}

这样不会造成代码部署在非FPM环境下造成问题。


使用fastcgi_finish_reques()函数后 需要注意以下几个注意点:

1、PHP 与 Web 服务器使用了PHP-FPM(FastCGI进程管理器),那通过fastcgi_finish_request() 函数能马上结束会话,而 PHP 线程可以继续在后台运行。也就是说只针对php-fpm的进程管理方式才能使用该函数。


2、只要代码运行到这个位置,就已经断开请求返回参数给客户端了。接下来的代码都和客户端没有关系了。也就是说对于输出在页面的内容必须放在fastcgi_finish_request()函数之前。


3、fastcgi_finish_request()函数 结束客户端连接之后,运行时间依然会受max_execution_time超时时间的影响,也就是说如果预计到代码在后端执行时间比较久,还是要设定set_time_limit(0)


4、在高并发下 执行时间过久也会导致fastcgi进程不够用,不能及时释放,这样Nginx就会报502 Bad Gateway错误了。


尾声:

1、主角是fastcgi_finish_request()函数,其实把要执行的代码放到该函数的后面,就可以了。

2、register_shutdown_function()函数,具体百度,这个函数主要是为了考虑修改成本,有的程序已经成型,不方便作大的调整,可以把函数提前注册,这样他是不会立即执行的。页面响应完毕后,再调用本函数。

3、建议不要滥用,适合一些耗时但流程简单的任务(比如发送邮件)。因为是后台执行,如果程序出错,前台是看不到的,需要有日志记录和重试机制。



fastcgi_finish_request()函数官方手册说明地址:https://www.php.net/manual/zh/function.fastcgi-finish-request.php

可参考鸟哥的博客:使用fastcgi_finish_request提高页面响应速度



你眼中的星辰大海,是我不曾见过的皓月星空    ----》【艺伎回忆录】



声明:禁止任何非法用途使用,凡因违规使用而引起的任何法律纠纷,本站概不负责。

小周博客
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

精彩评论

全部回复 0人评论 7,777人参与

loading