ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
[TOC] :-: ![PHP-FPM](https://img.kancloud.cn/c0/71/c071301f232b8f9623faee4b3e9284ac_724x304.png) ## 简介 **PHP-FPM**(FastCGI 进程管理器)用于替换 PHP FastCGI 的大部分附加功能,对于高负载网站是非常有用的。 它的功能包括: * 支持平滑停止/启动的高级进程管理功能; * 可以工作于不同的 uid/gid/chroot 环境下,并监听不同的端口和使用不同的 php.ini 配置文件(可取代 `safe_mode` 的设置); * stdout 和 stderr 日志记录; * 在发生意外情况的时候能够重新启动并缓存被破坏的 opcode; * 文件上传优化支持; * "慢日志" - 记录脚本(不仅记录文件名,还记录 PHP backtrace 信息,可以使用 ptrace或者类似工具读取和分析远程进程的运行数据)运行所导致的异常缓慢; * `fastcgi_finish_request()` - 特殊功能:用于在请求完成和刷新数据后,继续在后台执行耗时的工作(录入视频转换、统计处理等); * 动态/静态子进程产生; * 基本 SAPI 运行状态信息(类似 Apache 的 mod_status); * 基于 php.ini 的配置文件。 ## 工作原理 php-fpm启动 -> 生成 n 个 fast-cgi 协议处理进程 -> 监听一个端口等待任务 用户请求 -> web 服务器接收请求 -> 请求转发给 php-fpm -> php-fpm 交给一个空闲进程处理 -> 进程处理完成 -> php-fpm 返回给 web 服务器 -> web服务器接收数据 -> 返回给用户 ## 工作模式 php-fpm 进程管理一共有三种模式:ondemand、static、dynamic。 php-fpm 的工作模式和 nginx 类似,都是一个 master,多个 worker 模型。每个 worker 都在 accept 本 pool 内的监听套接字。 ### 静态模式 **static** php-fpm 启动时采用固定大小数量的worker,在运行期间也不会扩容,虽然也有1秒的定时器,仅限于统计一些状态信息,例如空闲worker个数,活动worker个数,网络连接队列长度等信息。 php-fpm.conf: ~~~text [test] listen = 127.0.01:9000 pm = static pm.max_children = 40 # 大于0 ,必须配置,且只有这一个参数生效 ~~~ ### 动态模式 **dynamic** 在 php-fpm 启动时,会初始启动一些 worker,在运行过程中动态调整 worke 数量,worke r的数量受限于pm.max_children 配置,同时受限全局配置 process.max 。 ~~~text [test] listen = 127.0.01:9000 pm = dynamic pm.max_children = 10 # 大于 0 pm.start_servers = 2 # 有效范围 [pm.min_spare_servers, pm.max_spare_servers] 如果没有配置,默认pm.min_spare_servers + (pm.max_spare_servers - pm.min_spare_servers) / 2 pm.min_spare_servers = 1 # <= pm.max_spare_servers pm.max_spare_servers = 6 ~~~ #### 原理 初始启动 `pm.min_spare_servers` 个 worker,而最大子进程数则由 `pm.max_children` 去控制,闲置的子进程数则由`pm.min_spare_servers`和`pm.max_spare_servers`控制,如果闲置的子进程超出了`pm.max_spare_servers`,则会被杀掉。master 进程中设置了 1秒定时器,检查空闲 worker 数量,按照一定策略动态调整 worker 数量,增加或减少。 #### 优缺点 - 优点:动态扩容,不浪费系统资源,master进程设置的1秒定时器对系统的影响忽略不计; - 缺点:如果所有worker都在工作,新的请求到来只能等待master在1秒定时器内再新建一个worker,这时可能最长等待1s; ### 按需分配 **ondemand** 在 php-fpm 启动的时候,不会给这个 pool 启动任何一个 worker,是按需启动,当有连接过来才会启动。 ~~~text [test] listen = 127.0.01:9000 pm = ondemand pm.process_idle_timeout = 60 # 大于0,如果不设置,默认10s pm.max_children = 10 # 大于0 ~~~ #### 原理 新建 worker 的触发条件是连接的到来,而不是实际的请求(只进行连接比如 telnet,不发请求数据也会新建 worker) worker 的数量受限于 `pm.max_children` 配置,同时受限全局配置 `process.max` master 进程中 1秒定时器会找到空闲 worker ,如果空闲时间超所 `pm.process_idle_timeout` ,则关闭,这个机制可能会关闭所有的 worker。 #### 优缺点 - 优点:按流量需求创建,不浪费系统资源(在硬件如此便宜的时代,这个优点略显鸡肋) - 缺点:由于 php-fpm 是短连接的,所以每次请求都会先建立连接,所以,在大流量的系统上 master 进程会变得繁忙,占用系统 cpu 资源,不适合大流量环境的部署 ## PHP-fpm 与 Nginx 的通信方式 ### **unix socket** * nginx 方面需要指定`fastcgi_pass unix:/xxx/xxx/xxx.sock`,如: ~~~text location ~ \.php$ { include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;; fastcgi_pass unix:/var/run/php7-fpm.sock; fastcgi_index index.php; } ~~~ * 相应地,php-fpm 方面需要指定`listen = /xxx/xxx/xxx.sock`,如: ~~~text listen = /var/run/php-fpm.sock ~~~ ### **tcp socket** * nginx 方面需要指定`fastcgi_pass ip:port`,如: ~~~text location ~ \.php$ { include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; } ~~~ * 相应地,php-fpm 方面需要指定`listen = ip:port`,如: ~~~json listen = 127.0.0.1:9000 ~~~ 带有权重的集群: ~~~json upstream api_fpm { server ip1:port1 weight=x1; server ip2:port2 weight=x2; } location ~ \.php$ { include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;; fastcgi_pass api_fpm; fastcgi_index index.php; } ~~~ ### 对比 * `unix socket`基于本地`.sock`文件通信,省去底层网络协议传输的消耗,更高效。 * `tcp socket`配合`nginx 的 upstream`实现了集群部署,更利于水平扩展。 * 基于上述特点: * 不需要集群,追求快速影响时,选择`unix socket`。 * 更注重服务稳定性和可扩展性时,选择`tcp socket`。