存档

2018年4月 的存档

php-fpm如何合理设置max_chindren和pm模式,包括开启status监听

2018年4月8日 没有评论

说明:以下设置仅供参考,并不代表每个服务器都可以这样设置。

在使用php-fpm+nginx模式的时候,如何合理设置pm模式和max_chindren的值,包括memory_limit的参考设置值;

 

首先,我们开启php-fpm的status来获得执行状态,

sudo vim /etc/php/5.x/fpm/pool.d/www.conf

找到status_path设置为自己想要访问的路径,比如设置为/status,那么通过域名/status即可访问。

保存,然后修改nginx的默认站点配置文件,我这里是default.conf,如果你在fastcgi_params里面已经设置了相关的参数,比如:

fastcgi_pass unix:/run/php/php5.6-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

那么你只需要在default.conf的server段中增加:

location ~ /status$ {include fastcgi_params;}即可,重启nginx和php-fpm,访问:域名/status就可以获得php-fpm的运行状态,比如:

pool: www
process manager: dynamic
start time: 07/Apr/2018:20:44:53 -0700
start since: 187
accepted conn: 5570
listen queue: 0
max listen queue: 0
listen queue len: 0
idle processes: 25
active processes: 7
total processes: 32
max active processes: 54
max children reached: 0
slow requests: 0

具体的参数代表含义,可以自行百度搜索。

使用htop命令查看单个php-fpm所申请的VIRT大小,我32G服务器是400左右(实际要除以8=M,就是:50M左右),如果按照每个进程消耗50M*1.5倍=75M左右,如果你的服务器内存是32G,我们假设可用于php-fpm的内存为60%=20G,则:20*1024/75=273,所以,一般我们建议max_chindren最大为273,最好还是设置为:8的倍数,所以我设置为256.

然后我们可以根据域名/status的结果来合理设置其他参数(pm.start_servers和pm.min_spare_servers和pm.max_spare_servers)

在php.ini中,我们可以看到memory_limit有一句这样的原文,Maximum amount of memory a script may consume (128MB),就是说单个进程使用的最大内存大小,这个参数吧,当然不能低于刚刚计算的75M了,一般我们可以设置为3倍,则75*3=225M左右(建议:128,256,512,1024…)

这里假如有攻击的话,max_chindren=256,memory_limit=256,256*256=64G,很明显会导致内存爆满,所以如果想又保持性能,又能一定程度上防止内存爆满,可以将max_chindren设置的低一点,memory_limit可以设置为每个进程消耗的值(一般不建议低于128M吧,如果是独立服务器的话)。

当然,如果php.ini里面的memory_limit设置后无效,你可以关注下:/etc/php/5.x/fpm/pool.d/www.conf中的php_admin_value[memory_limit] =参数。

=============================

我们关注下 PHP-FPM 的运行方式:
pm = static模式:

始终保持一个固定数量的子进程,这个数由pm.max_children定义,这种方式很不灵活,也通常不是默认的。
优点是不用动态的判断负载情况,提升性能;缺点是多占用些系统内存资源。在内存足够的前提下性能最强
用此模式每天需要设置固定时间重启php
pm = dynamic模式:

启动时,会产生固定数量的子进程(由pm.start_servers控制)可以理解成最小子进程数,而最大子进程数则由pm.max_children去控制,OK,这样的话,子进程数会在最大和最小数范围中变化,还没有完,闲置的子进程数还可以由另2个配置控制,分别是pm.min_spare_servers和pm.max_spare_servers,也就是闲置的子进程也可以有最小和最大的数目,而如果闲置的子进程超出了pm.max_spare_servers,则会被杀掉。
pm = ondemand模式:

这种模式和pm = dynamic相反,把内存放在第一位,他的工作模式很简单,每个闲置进程,在持续闲置了pm.process_idle_timeout秒后就会被杀掉,有了这个模式,到了服务器低峰期内存自然会降下来,如果服务器长时间没有请求,就只会有一个php-fpm主进程,当然弊端是,遇到高峰期或者如果pm.process_idle_timeout的值太短的话,无法避免服务器频繁创建进程的问题,因此pm = dynamic和pm = ondemand谁更适合视实际情况而定。
PHP-FPM 子进程数量,是不是越多越好?

当然不是,pm.max_chindren,进程多了,增加进程管理的开销以及上下文切换的开销。

更核心的是,能并发执行的 php-fpm 进程不会超过 cpu 个数。

如何设置,取决于你的代码

如果代码是 CPU 计算密集型的,pm.max_chindren 不能超过 CPU 的内核数。
如果不是,那么将 pm.max_chindren 的值大于 CPU 的内核数,是非常明智的。
国外技术大拿给出这么个公式:

在 N + 20% 和 M/m 之间。

N 是 CPU 内核数量。
M 是 PHP 能利用的内存数量。
m 是每个 PHP 进程平均使用的内存数量。
适用于 dynamic 方式。

static方式:M/(m * 1.2)

当然,还有一种保险的方式,来配置 max_children。适用于 static 方式。

先把 max_childnren 设置成一个比较大的值。
稳定运行一段时间后,观察 php-fpm 的 status 里的 max
active processes 是多少
然后把 max_children 配置比它大一些就可以了。
pm.max_requests:指的是每个子进程在处理了多少个请求数量之后就重启。

这个参数,理论上可以随便设置,但是为了预防内存泄漏的风险,还是设置一个合理的数比较好

=============================

所以,我的服务器32G内存设置为:

memory_limit = 256M

pm = dynamic
pm.max_children = 256
pm.start_servers = 32
pm.min_spare_servers = 16
pm.max_spare_servers = 32

根据php-fpm的status监控数据显示,服务器状态运行良好。

css.php