PHP

PHP-FPM 进程管理器专家 - 了解更多

silverwq
2022-07-05 / 0 评论 / 316 阅读 / 正在检测是否收录...

概述

FPM(FastCGI Process Manager)是PHP FastCGI运行模式的一个进程管理器,从它的定义可以看出,FPM的核心功能是进程管理。
FastCGI是Web服务器(如:Nginx、Apache)和处理程序之间的一种通信协议,它是与Http类似的一种应用层通信协议,注意:它只是一种协议!
首先,PHP只是一个脚本解析器,没有实现http协议,只有实现了FastCGI协议。所以为了能接收http请求,就需要第三方实现http协议的软件,例如nginx。工作原理如下:
nginx接收http请求,然后通过fastcgi协议发送给php,php解析请求,结果通过fastcgi协议返回给nginx,然后nginx将响应结果通过http协议返回给客户端。
l8kxni7j.png

基本实现

fpm的实现就是创建一个master进程,在master进程中创建并监听socket,然后fork出多个子进程,这些子进程各自accept请求。
子进程的处理非常简单,它在启动后阻塞在accept上(通过这些kqueue、epoll、poll、select技术来监听),有请求到达后开始读取请求数据,读取完成后开始处理然后再返回,在这期间是不会接收其它请求的,也就是说fpm的子进程同时只能响应一个请求,只有把这个请求处理完成后才会accept下一个请求。

fpm的master进程与worker进程之间不会直接进行通信,master通过共享内存获取worker进程的信息,比如worker进程当前状态、已处理请求数等,当master进程要杀掉一个worker进程时则通过发送信号的方式通知worker进程。

配置

子进程监听多个端口

fpm可以同时监听多个端口,每个端口对应一个worker pool,而每个pool下对应多个worker进程,类似nginx中server概念。在php-fpm.conf中通过[pool name]声明一个worker pool

[web1]
listen = 127.0.0.1:9000
...

[web2]
listen = 127.0.0.1:9001
...

fpm子进程数量配置

pm有三个值,分别代表3种进程管理方式:
dynamic
表示php-fpm进程数是动态的,如果请求较多,则会自动增加,内存小的建议用这个。
动态进程管理,首先在fpm启动时按照pm.start_servers初始化一定数量的worker,运行期间如果master发现空闲worker数低于pm.min_spare_servers配置数(表示请求比较多,worker处理不过来了)则会fork worker进程,但总的worker数不能超过pm.max_children,如果master发现空闲worker数超过了pm.max_spare_servers(表示闲着的worker太多了)则会杀掉一些worker(通过定时器实现,一定时间后触发某个事件),避免占用过多资源,master通过这4个值来控制worker数。

pm.start_servers = 8 #dynamic模式下开机的进程数量。
pm.max_children = 15 #最大的数量
pm.min_spare_servers = 6 #dynamic模式下最小php-fpm进程数量。
pm.max_spare_servers = 15 #dynamic模式下最大php-fpm进程数量。

static
表示php-fpm的进程数自始至终都是pm.max_children指定的数量,不再增加或减少,这个值原则上是越大越好,php-cgi的进程多了就会处理的很快,排队的请求就会很少,不过也需要根据服务器的性能来配置,正常情况下,一个php-fpm进程内存在30M左右,不过也不好说,最好留给60%的内存给php-fpm进程就好了。内存大的建议用这个。
这种方式比较简单,在启动时master按照pm.max_children配置fork出相应数量的worker进程,即worker进程数是固定不变的

pm.max_children = 15 #static模式下生效,dynamic不生效。

ondemand
每个闲置进程在持续闲置了pm.process_idle_timeout秒后就会被杀掉,如果服务器长时间没有请求,就只会有一个php-fpm主进程。适用于微小内存,例如512MB或者256MB内存,以及对可用性要求不高的环境。
这种方式一般很少用,在启动时不分配worker进程,等到有请求了后再通知master进程fork worker进程,总的worker数不超过pm.max_children,处理完成后worker进程不会立即退出,当空闲时间超过pm.process_idle_timeout后再退出

pm.process_idle_timeout = 900 # 900s之后不管是否执行完成,直接杀死进程,这个要注意

最大连接时长

pm.request_terminate_timeout
表示将执行时间太长的进程直接终止的时间,单位是秒。如果是设置为0表示不超时,一直保持连接,直到返回结果。可以设置个15分钟,也就是900秒。

慢日志配置

request_slowlog_timeout
这参数设置多长时间开始记录日志,一般设置为:request_slowlog_timeout = 10s
slowlog
这个参数用于配置慢日志文件记录的位置。slowlog = log/$pool.log.slow,log是相对路径。

打开的最大的文件数量

rlimit_files
配置php-fpm可以打开的最大的文件数量,默认1024,此值可以不需要配置,rlimit_files = 1024

缺点

假设我们使用 Nginx 提供 HTTP 服务(Apache 同理),所有客户端发起的请求最先抵达的都是 Nginx,然后 Nginx 通过 FastCGI 协议将请求转发给 PHP-FPM 处理,PHP-FPM 的 Worker 进程 会 抢占式 的获得 CGI 请求进行处理,这个处理指的就是,等待 PHP 脚本的解析,等待业务处理的结果返回,完成后回收子进程,这整个的过程是 阻塞等待 的,也就意味着 PHP-FPM 的进程数有多少能处理的请求也就是多少,假设 PHP-FPM 有 200 个 Worker 进程,一个请求将耗费 1 秒的时间,那么简单的来说整个服务器理论上最多可以处理的请求也就是 200 个,QPS 即为 200/s,在高并发的场景下,这样的性能往往是不够的,尽管可以利用 Nginx 作为负载均衡配合多台 PHP-FPM 服务器来提供服务,但由于 PHP-FPM 的阻塞等待的工作模型,一个请求会占用至少一个 MySQL 连接,多节点高并发下会产生大量的 MySQL 连接,而 MySQL 的最大连接数默认值为 100,尽管可以修改,但显而易见该模式没法很好的应对高并发的场景。

参考

https://github.com/pangudashu/php7-internal/blob/master/1/fpm.md

0

评论 (0)

取消