aaLiweipeng 2020-04-25
PHP-FPM 是一种 Master / Worker 多进程运行模式,进程的数量可以通过 php-fpm.conf 进行具体的配置。
Master 进程主要负责 CGI、PHP 环境的初始化、事件循环、监听子进程状态等。
Woker 主要负责处理 PHP 的请求。
PHP-FPM 支持三种运行模式,分别是 静态模式 static
、按需模式 ondemand
、动态模式 dynamic
。
直接开启指定数据量的 PHP-FPM 进程,不再增加或者减少。
启动固定数量的进程,占用内存高。
但是在用户请求波动大的时候,对 Linux 系统的处理耗费的系统资源底。
PHP-FPM 的 Master 不会 Fork 任何的子进程,只有收到用户请求时才会 fork worker 进程,这种模式很少使用。
因为它基本无法适应由一定量级的线上业务,由于 PHP-FPM 是短连接,所以每次请求都会先建立连接。
在大流量的系统上 Master 进程会变得非常繁忙,占用系统 CPU 资源,不适合大流量环境的部署。
启动时分配固定的进程,随着请求数的变化,在设定的浮动范围调整 worker 进程。
开启一定数量的 PHP-FPM 进程,当请求量变大的时候,动态增加 PHP-FPM 进程数量达到上限,当空闲的时候自动释放空闲进程数到下一个下限。
会根据 max、min、idle children 配置,动态的调整进程数量。
在用户请求波动较大,或者瞬间请求量变大的时候,会进行大量进程的创建和销毁操作,而引起 Linux 系统的负载增高。
PHP-FPM 使用 master/worker 架构设计。
分别调用 fcgi_init() 函数 和 sapi_start_up() 函数,注册进程信号以及初始化 sapi_globals 全局变量。
由 cgi_sapi_module.start_up 触发,实际上调用 php_cgi_start_up 函数,而 php_cgi_start_up 内部又调用 php_module_start_up 执行。
php_module_start_up 主要功能包括:
1、加载和解析 PHP 配置文件。
2、加载 PHP 模块并记入函数符号表 (function_table)。
3、加载 Zend 扩展。
4、设置禁用函数和类库配置。
5、注册回收内存方法。
执行 fpm_init() 函数,负责解析 php-fpm.conf 文件配置,获取进程相关参数,例如:允许进程打开的最大文件数。
初始化进程池及事件模型等操作。
执行 fpm_run() 函数,运行后主进程发送阻塞。
此阶段包括 fork 子进程和事件循环两个部分:
1、fork 子进程交由 fpm_children_create_initial 函数处理。
2、事件循环通过 fpm_event_loop 函数处理,其内部是一个死循环,负责事件的收集工作。
woker 进程分为 接收客户端请求、处理请求、请求结束三个阶段。
执行 fcgi_accept_request 函数,其内部通过调用 accept 函数获取客户端请求。
首先,分别调用 fpm_request_info、php_request_start_up 获取请求内容及注册全局变量($_GET、$_POST、$_SERVER、$_ENV、$FILES)。
然后,根据请求信息调用 php_fopen_primary_script 访问脚本文件。
最后,交给 php_execute_script 执行。执行 php_execute_script 内部调用 zend_execute_scripts 方法将脚本交给 zend 引擎处理。
执行 php_request_shutdown 函数,此时回调 register_shutdown_function 注册的函数及 __destruct() 方法,发送响应内容、释放内存等操作。