性能调优 PHP-FPM:如何调整子进程数量

性能调优 PHP-FPM:如何调整子进程数量
pm = dynamic
pm.max_children = 20
pm.start_servers = 10
pm.min_spare_servers = 2
pm.max_spare_servers = 4
pm.max_requests = 1000

假设使用上述配置。是否可以知道以下内容?

  1. 请求队列中有多少未完成的请求等待服务?
  2. 请求在被服务之前在队列中等待的平均延迟是多少?

答案1

但最重要的问题——“如何调整 PHP-FPM 子进程的数量”——可以更简单地回答,即“内存可以容纳多少就设置多少”。调查我的非常小的 VPS,我可以看到:

$ grep memory_limit /etc/php/7.4/fpm/php.ini 

    memory_limit = 128M

PHP 的默认内存限制为 128 MB,远远超出了我所使用的范围。

$ free -m
           total used free shared buff/cache available
    Mem:     976  468   68      0        439       369
    Swap:      0    0    0

此 VPS 有 369 MB 可用空间,因此尝试安装超出其容量的 PHP 实例是没有意义的。

将 PHP Max Mem 和 Mem Free 数字放入变量并用 avail/maxmem 除以,可得出:

$ PHPSIZE=`grep memory_limit /etc/php/7.4/fpm/php.ini | tr -dc '0-9'`
$ AVAIL=`free -m | grep "^Mem" | rev | cut -d' ' -f 1 | rev`
$ echo "scale=3;$AVAIL/$PHPSIZE" | bc

    2.875

因此在这种情况下,369 可用兆字节只能容纳 2 个 128 兆字节的 php 实例,假设 memory_limit 最大值反映实际所需的最大内存。

可以通过以下方式进行调查内存获取峰值使用情况()功能。

也可以看看:

答案2

  1. 假设使用 Linux unix 套接字,可以使用以下命令查看待处理的连接党卫军(包:iproute2)和网络状态(包:net-tools)。

使用 ss;

$ ss -lf unix src /run/php\*

将显示类似输出

Netid      State    Recv-Q Send-Q  Local Address:Port                Peer Address:Port      Process      
u_str      LISTEN   5      4096    /run/php/php7.4-fpm.sock 7082746  * 0           

相反,Netstat 会显示一个列表:

$ netstat -xpa | grep -E "^(Active|Proto)|php"

Active UNIX domain sockets (servers and established)
Proto RefCnt Flags       Type       State         I-Node   PID/Program name     Path
unix  2      [ ACC ]     STREAM     LISTENING     7066676  1021364/php-fpm: ma  /run/php/php7.4-fpm.sock
unix  3      [ ]         STREAM     CONNECTED     7068154  1021391/php-fpm: po  /run/php/php7.4-fpm.sock
unix  3      [ ]         STREAM     CONNECTED     7067205  1021406/php-fpm: po  /run/php/php7.4-fpm.sock
unix  3      [ ]         STREAM     CONNECTED     7067203  1021407/php-fpm: po  /run/php/php7.4-fpm.sock
  1. 潜伏。

这不是那么简单;有两种方法,基准测试和日志记录。

基准测试可以使用各种各样的工具,例如阿帕奇长凳或者围城

例子AB用法:

$ ab -c 50 -n 100 "http://hp/delay.php"

将打开 50 个同时连接并发出 100 个请求(每个请求 2 个)。我生成有用的输出,例如:

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    2   1.5      2       4
Processing:  1002 2079 716.5   2010    3130
Waiting:     1002 2079 716.5   2010    3129
Total:       1004 2081 716.9   2011    3133

Percentage of the requests served within a certain time (ms)
  50%   2011
  66%   2121
  75%   2998
  80%   3005
  90%   3013
  95%   3120
  98%   3127
  99%   3133
 100%   3133 (longest request)

围城很相似:

$ siege -c 200 -r 2 -d 0 --no-parser "http://hp/delay.php"
** SIEGE 4.0.4
** Preparing 200 concurrent users for battle.
The server is now under siege...
Transactions:                400 hits
Availability:             100.00 %
Elapsed time:              10.29 secs
Data transferred:           0.01 MB
Response time:              4.58 secs
Transaction rate:          38.87 trans/sec
Throughput:             0.00 MB/sec
Concurrency:              178.12
Successful transactions:         400
Failed transactions:               0
Longest transaction:            7.27
Shortest transaction:           1.00

否则,日志会记录每个请求的实际延迟和等待时间。在Apache 2.4.13 及更高版本的日志记录,有一个日志指令“%^FB”,给出请求到达和第一个字节或后端输出之间经过的微秒数。另一个选项是在自定义日志字符串中使用“%{begin:msec}t %{end:msec}t”。

另一个信息来源是 PHP 的fpm_get_status()23。此信息的简单用途如下:

echo '<pre><?php print_r(fpm_get_status());' > /var/www/html/testfpmstatus.php

$ curl http://localhost/testfpmstatus.php

<pre>Array
(
    [pool] => www
    [process-manager] => dynamic
    [start-time] => 1659800269
    [start-since] => 72
    [accepted-conn] => 2
    [listen-queue] => 0
    [max-listen-queue] => 0
    [listen-queue-len] => 0
    [idle-processes] => 9
    [active-processes] => 1
    [total-processes] => 10
    [max-active-processes] => 1
    [max-children-reached] => 0
    [slow-requests] => 0
    [procs] => Array
        (
            [0] => Array
                (
                    [pid] => 1024097
                    [state] => Idle
                    [start-time] => 1659800269
                    [start-since] => 72
                    [requests] => 1
                    [request-duration] => 479
                    [request-method] => GET
                    [request-uri] => /testfpmstatus.php
                    [query-string] => 
                    [request-length] => 0
                    [user] => -
                    [script] => -
                    [last-request-cpu] => 0
                    [last-request-memory] => 2097152
                )
            [1] => Array

也可以看看:

答案3

简短回答:不。

长答案:这完全取决于应用程序以及应用程序进行的处理量和类型。

例如:

在应用程序 A 中,一个典型的请求需要 50 毫秒才能完成。这意味着单个服务器每秒可以处理 20 个请求。

在应用程序 B 中,一个典型的请求需要 200 毫秒才能完成。那么单个服务器每秒可以处理 5 个请求。

确定问题答案的唯一方法是在环境中测量它们。变量太多,无法通过推理得到结果。

欲了解更多信息,请查看您能帮助我进行容量规划吗?

相关内容