首页 > 开发 > PHP > 正文

深入剖析浏览器退出之后php还会继续执行么

2024-05-04 22:30:28
字体:
来源:转载
供稿:网友

前提:这里说的是典型的lnmp结构,nginx+php-fpm的模式

如果我有个php程序执行地非常慢,甚至于在代码中sleep(),然后浏览器连接上服务的时候,会启动一个php-fpm进程,但是这个时候,如果浏览器关闭了,那么请问,这个时候服务端的这个php-fpm进程是否还会继续运行呢?

今天就是要解决这个问题。

最简单的实验

最简单的方法就是做实验,我们写一个程序:在sleep之前和之后都用file_put_contents来写入日志:

<?phpfile_put_contents('/tmp/test.log', '11111' . PHP_EOL, FILE_APPEND | LOCK_EX);sleep(3);file_put_contents('/tmp/test.log', '2222' . PHP_EOL, FILE_APPEND | LOCK_EX);

实际操作的结果是,我们在服务器sleep的过程中,关闭客户端浏览器,2222是会被写入日志中。

那么就意味着浏览器关闭以后,服务端的php还是会继续运行的?

ignore_user_abort

老王和diogin提醒,这个可能是和php的ignore_user_abort函数相关。

于是我就把代码稍微改成这样的:

<?phpignore_user_abort(false);file_put_contents('/tmp/test.log', '11111' . PHP_EOL, FILE_APPEND | LOCK_EX);sleep(3);file_put_contents('/tmp/test.log', '2222' . PHP_EOL, FILE_APPEND | LOCK_EX);

发现并没有任何软用,不管设置ignore_user_abort为何值,都是会继续执行的。

但是这里有一个疑问: user_abort是什么?

文档对cli模式的abort说的很清楚,当php脚本执行的时候,用户终止了这个脚本的时候,就会触发abort了。然后脚本根据ignore_user_abort来判断是否要继续执行。

但是官方文档对cgi模式的abort并没有描述清楚。感觉即使客户端断开连接了,在cgi模式的php是不会收到abort的。

难道ignore_user_abort在cgi模式下是没有任何作用的?

是不是心跳问题呢?

首先想到的是不是心跳问题呢?我们断开浏览器客户端,等于在客户端没有close而断开了连接,服务端是需要等待tcp的keepalive到达时长之后才会检测出来的。

好,需要先排除浏览器设置的keepalive问题。

抛弃浏览器,简单写一个client程序:程序连接上http服务之后,发送一个header头,sleep1秒就主动close连接,而这个程序并没有带http的keepalive头。

程序如下:

package mainimport "net"import "fmt"import "time"func main() {  conn, _ := net.Dial("tcp", "192.168.33.10:10011")  fmt.Fprintf(conn, "GET /index.php HTTP/1.0/r/n/r/n")  time.Sleep(1 * time.Second)  conn.Close()  return}

服务端程序:

<?phpignore_user_abort(false);file_put_contents('/tmp/test.log', '11111' . PHP_EOL, FILE_APPEND | LOCK_EX);sleep(3);file_put_contents('/tmp/test.log', '2222' . PHP_EOL, FILE_APPEND | LOCK_EX);            
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表