PHP一次请求的生命周期
文章目录
一个请求进来,到达nginx或者是apache,再到php,直到出现响应,发生了什么事情
PHP的运行模式
PHP两种运行模式是WEB模式、CLI模式。
无论哪种模式,PHP工作原理都是一样的,作为一种SAPI运行。
PHP脚本执行的开始,都是通过SAPI接口进行的
第一阶段:SAPI接口,模块初始化阶段
SAPI是什么?
Server Application Programming Interface 服务端应用编程接口
这是 PHP 内核提供给外部调用其服务的接口,即外部系统可以通过 SAPI 来调用 PHP 提供的编译脚本、执行脚本的服务。
SAPI提供给了外部应用跟php通信的管道,这个外部应用包括不限于Apache,httpd,liunx终端等
PHP 中实现的 SAPI 有很多,CLI、FPM 是我们比较常见的。
在使用Apache作为Web服务器的时候:
PHP总是作为Apache的模块,随着Apache的启动而运行的。
当给定的SAPI启动时,PHP进入初始化内核子系统,主要对PHP框架,zend引擎的初始化操作,这个阶段一般是在SAPI启动时执行一次。
在使用Nginx作为Web服务器的时候:
因为Nginx不能直接和PHP通信,所以他们之间要通过 fast-cgi 协议才能互相理解。
php-fpm 即 php-Fastcgi Process Manager,是 FastCGI 的实现,并提供了进程管理的功能。
对于php-fpm而言,就是在master进程启动时执行,加载PHP拓展,并调用模块初始化例程 MINIT , 这使得每个扩展可以初始化内部变量、分配资源、注册资源处理器,以及向zend注册自己的函数,以便于脚本调用这其中的函数时候zend知道执行哪些代码。再预先fork 多个 worker 进程,accept请求并执行。
worder 进程的生命周期如下图:
第二阶段:请求初始化阶段
当一个请求发生时,在处理请求前需要经历的一个阶段 :
-
Nginx 解析一个请求
-
当符合php脚本请求的规则的时候,会把这个请求交给反向代理中的fast-cgi模块
-
Nginx 的 fast-cgi 模块会遵循 fast-cgi协议 将这个请求转发给 proxy_pass 指定的上游服务:php-fpm
-
SAPI层将控制权交给PHP层。于是PHP设置了用于回复本次请求所需的环境变量。同时,它还建立一个变量表,用来存放执行过程 中产生的变量名和值。PHP调用各个模块的RINIT方法,即“请求初始化”。
一个经典的例子是Session模块的RINIT,如果在php.ini中 启用了Session模块,那在调用该模块的RINIT时就会初始化$_SESSION变量,并将相关内容读入;RINIT方法可以看作是一个准备过程, 在程序执行之间就会自动启动。
第三阶段:php脚本执行阶段
php代码解析执行的过程,Zend引擎接管控制权。
- Scanning(Lexing) ,将PHP代码转换为语言片段(Tokens) (扫描–语言片段)
- Parsing, 将Tokens转换成简单而有意义的表达式**(解析–表达式)**
- Compilation, 将表达式编译成Opocdes**(编码-opcodes)**
- Execution, 顺次执行Opcodes,每次一条,从而实现PHP脚本的功能。(执行opcodes)
第四阶段:请求结束阶段
请求处理完成后,就进入了 结束阶段。
- 执行flush,输出响应内容
- PHP启动清理程序,它会按顺序调用各个模块的RSHUTDOWN方法。 RSHUTDOWN用以清除程序运行时产生的符号表,执行垃圾清理过程,也就是对每个变量调用unset函数。
- worker进程关闭该请求连接,继续等待 accept下一个请求。