max_children
Categories:
PHP FPM Max Children
在 php fpm 的 error log 发现执行绪不太够用,需要设定开启新执行绪
[24-Oct-2018 07:43:58] WARNING: [pool www] server reached pm.max_children setting (5), consider raising it
[24-Oct-2018 08:27:52] WARNING: [pool www] server reached pm.max_children setting (5), consider raising it
[24-Oct-2018 10:57:17] WARNING: [pool www] server reached pm.max_children setting (5), consider raising it
[24-Oct-2018 11:37:32] WARNING: [pool www] server reached pm.max_children setting (5), consider raising it
设定档路径
/etc/php/7.1/fpm/pool.d/www.conf
在设定档中可以看到类似以下的设定方式
pm.max_children = 10
pm.start_servers = 4
pm.min_spare_servers = 2
pm.max_spare_servers = 8
Process Manager 行程调配规则参数说明
参数 | 说明 |
---|---|
pm | PHP-FPM Process Manager 行程调配规则 |
pm.start_servers | PHP-FPM 服务在一开始启动时,要配置多少个行程 |
pm.min_spare_servers | PHP-FPM 最小闲置行程的数量 |
pm.max_spare_servers | PHP-FPM 最大闲置行程的数量 |
pm.max_requests | 单一 PHP-FPM 最多可以处理多少个连线,当一个工作行程处理的连线数达到这个值的时候,就会强制关闭此行程,重新产生另一个新的行程 |
pm = dynamic
参数 | 说明 |
---|---|
static | 固定行程数量(数量为 pm.max_children) ,效能很好,但很佔记忆体 |
dynamic | 动态行程数量(根据 pm.max_children、pm.start_servers、pm.min_spare_servers、pm.max_spare_servers 动态调整),根据使用量用多少开多少,但当使用量比较低时,会保留一些行程,随时等着接收新的连线 |
ondemand | 动态行程数量(根据 pm.max_children、pm.start_servers、pm.min_spare_servers、pm.max_spare_servers 动态调整),用多少开多少 |
pm.max_children 最大执行程序数量
最大执行程序数量是针对自己的主机规格不同去做设定的,当你主机有较大的记忆体,则可以设定更多的执行程序
Total Max Processes = (Total Ram - (Used Ram + Buffer)) / (Memory per php process)
最大执行程序 = (总记忆体 - (已使用记忆体 + Buffer)) / (每个 php 执行绪需要记忆体)
pm.max_children 数量:可用记忆体(MB) / 大约 50MB
确认每个 php 执行绪需要记忆体
因为每个 php 执行的记忆体及效率会针对不同的程式环境不同,而有不同的消耗记忆体,可以使用下列指令去取得 php-fpm 执行绪消耗的记忆体数量
ps -ylC
php-fpm 执行绪完整名称
–sort:rss
范例
其中的 php-fpm 执行绪完整名称
要看看你系统是用哪个版本的 php,而会有不同版本名称的 php-fpm,像是:
ps -ylC php-fpm --sort:rss
ps -ylC php-fpm7.0 --sort:rss
ps -ylC php-fpm7.1 --sort:rss
在列出来 php-fpm 使用的资源后,可以看到 RSS
栏位为使用的记忆体大小,31692
表示为 31692 kb
,大概就是 31M
$ ps -ylC php-fpm7.1 --sort:rss
S UID PID PPID C PRI NI RSS SZ WCHAN TTY TIME CMD
S 33 22275 16692 1 80 0 31692 212882 - ? 08:00:00 php-fpm7.0
S 33 22092 16692 1 80 0 40708 231684 - ? 08:00:02 php-fpm7.0
S 33 22023 16692 1 80 0 41136 231888 - ? 08:00:05 php-fpm7.0
S 33 22038 16692 1 80 0 41204 231744 - ? 08:00:04 php-fpm7.0
但每个 php-fpm 程序的记忆体不尽相同,我们可以用下列指令去计算平均使用的记忆体大小是多少
ps –no-headers -o “rss,cmd” -C
php-fpm 执行绪完整名称
| awk ‘{ sum+=$1 } END { printf ("%d%s\n", sum/NR/1024,“Mb”) }’
也是一样针对你系统是用哪个版本的 php,而会有不同版本名称的 php-fpm,像是:
ps --no-headers -o "rss,cmd" -C php-fpm | awk '{ sum+=$1 } END { printf ("%d%s\n", sum/NR/1024,"Mb") }'
ps --no-headers -o "rss,cmd" -C php-fpm7.0 | awk '{ sum+=$1 } END { printf ("%d%s\n", sum/NR/1024,"Mb") }'
ps --no-headers -o "rss,cmd" -C php-fpm7.1 | awk '{ sum+=$1 } END { printf ("%d%s\n", sum/NR/1024,"Mb") }'
抓出来的平均使用记忆体大概为 44 MB
,但为了抓 Buffer,我们大概抓 50 MB
左右
$ ps --no-headers -o "rss,cmd" -C php-fpm7.0 | awk '{ sum+=$1 } END { printf ("%d%s\n", sum/NR/1024,"Mb") }'
44Mb
确认可用的记忆体数量
php-fpm 可以用的记忆体为:剩馀还可用的记忆体 + (php-fpm 平均使用记忆体 * 目前 php-fpm 开启数量)
使用 free -m
取得目前的记忆体使用状况,总记忆体是 3272 M
,已经使用了 1539M
,剩馀还可用的记忆体有 1021 M
$ free -m
total used free shared buff/cache available
Mem: 3762 1539 1021 84 2417 2686
Swap: 0 0 0
而从下列指令中,取得 php-fpm 平均使用记忆体为 44M
ps –no-headers -o “rss,cmd” -C
php-fpm 执行绪完整名称
| awk ‘{ sum+=$1 } END { printf ("%d%s\n", sum/NR/1024,“Mb”) }’
从下列指令中列出目前所有 php-fpm 执行绪数量为 41 个
(直接去计算清单出现几行 php-fpm 资源状况即可知道总共开了几个 php-fpm 执行绪)
ps -ylC
php-fpm 执行绪完整名称
–sort:rss
所以 php-fpm 可以用的记忆体为 1021 M
+ 44 M
* 41 个
= 2743M
最大执行程序数量 = php-fpm 可以用的记忆体 / 每个 php 执行绪需要记忆体(Buffer 数值)
2743M / 50M = 54.86
为了不要让所有记忆题全部消耗完,而没有空间去执行其他非 php 的程序,所以我们这边会抓 pm.max_children
大概最多使用个 50 个
执行绪
pm.max_children = 50
start_server 官方建议算法是 min_spare_servers + (max_spare_servers - min_spare_servers) / 2
min_spare_servers 跟 max_spare_servers 就取个大概就好,不要让他一直开开关关即可
pm.start_servers = 20
pm.min_spare_servers = 13
pm.max_spare_servers = 26
防止 php-fpm 执行绪处理过多 request 导致 Memory leak
pm.max_requests = 500
request_terminate_timeout = 30s
让每个子执行绪同时处理超过 500 个 request 就自动移除此执行绪,避免 Memory Leak 执行绪卡在那边动弹不得
而执行时间超过 30 秒的请求则自动中断掉,建议设定为与 php.ini
的 max_execution_time
相同
最后设定值会像是:
pm = dynamic
pm.max_children = 50
pm.start_servers = 20
pm.min_spare_servers = 13
pm.max_spare_servers = 26
pm.max_requests = 500
request_terminate_timeout = 30s
记录观察
为了持续观察 php-fpm 执行序地处理状况,我们可以把请求执行时间过慢的 Request 记录下来,在之后后续可以持续做除错改进,这裡设定纪录执行超过 10 秒的执行绪状况
; slowlog = /var/log/php7.0-fpm-$pool.log.slow
slowlog = /var/log/php7.1-fpm-$pool.log.slow
request_slowlog_timeout = 10s
设定完成后可以进行测试,确认改过的设定档案没有问题
php-fpm7.0 -t
php-fpm7.1 -t
$ php-fpm7.1 -t
[03-Jul-2019 15:53:15] NOTICE: configuration file /etc/php/7.1/fpm/php-fpm.conf test is successful
确认后记得重启 php-fpm 服务即可生效
sudo service php7.0-fpm restart
sudo service php7.1-fpm restart
参考资料
- Nginx 与 PHP-FPM 最佳化效能设定教学与技巧 - G. T. Wang
- Determining the correct number of child processes for PHP-FPM on NGinx
- 【整理】php-fpm.conf中的pm.max_children到底应该设置为多少 – 在路上
- PHP-FPM: Process Management | Servers for Hackers
- Determining the correct number of child processes for PHP-FPM on NGinx
- How To: Solve PHP-FPM server reached max_children | Webcore Community | Webcore Cloud