LNMP的php-fpm配置

LNMP的php-fpm配置

Administrator 1096 2018-06-13

本文主要介绍LNMP的php-fpm的pool配置,以及php-fpm的慢执行日志,open_basedir、进程管理相关的知识。


php-fpm的pool

  • 所谓的php-fpm的pool,实际上就是指我们在/usr/local/php-fpm/etc/下的php-fpm.conf配置文件中定义的[www]块的配置,整个[www]称为一个pool,实际上php-fpm支持定义多个pool,每个pool可以定义不同的pid,可以查看系统进程看到运行的pool:

    [root@evobot etc]# ps aux|grep php
    root       799  0.0  0.0 112676   984 pts/1    R+   21:10   0:00 grep --color=auto php
    root      9240  0.0  0.2 227224  4960 ?        Ss   6月11   0:06 php-fpm: master process (/usr/local/php-fpm/etc/php-fpm.conf)
    php-fpm   9241  0.0  0.2 229308  5044 ?        S    6月11   0:00 php-fpm: pool www
    php-fpm   9242  0.0  0.2 229308  5044 ?        S    6月11   0:00 php-fpm: pool www
    php-fpm   9243  0.0  0.2 229308  5044 ?        S    6月11   0:00 php-fpm: pool www
    php-fpm   9244  0.0  0.2 229308  5044 ?        S    6月11   0:00 php-fpm: pool www
    php-fpm   9245  0.0  0.2 229308  5048 ?        S    6月11   0:00 php-fpm: pool www
    php-fpm   9246  0.0  0.2 229308  5048 ?        S    6月11   0:00 php-fpm: pool www
    php-fpm   9247  0.0  0.2 229308  5048 ?        S    6月11   0:00 php-fpm: pool www
    php-fpm   9248  0.0  0.2 229308  5048 ?        S    6月11   0:00 php-fpm: pool www
    php-fpm   9249  0.0  0.2 229308  5048 ?        S    6月11   0:00 php-fpm: pool www
    php-fpm   9250  0.0  0.2 229308  5048 ?        S    6月11   0:00 php-fpm: pool www
    php-fpm   9251  0.0  0.2 229308  5048 ?        S    6月11   0:00 php-fpm: pool www
    php-fpm   9252  0.0  0.2 229308  5048 ?        S    6月11   0:00 php-fpm: pool www
    php-fpm   9253  0.0  0.3 229308  6736 ?        S    6月11   0:00 php-fpm: pool www
    php-fpm   9254  0.0  0.2 229308  5048 ?        S    6月11   0:00 php-fpm: pool www
    php-fpm   9255  0.0  0.3 229308  6740 ?        S    6月11   0:00 php-fpm: pool www
    php-fpm   9256  0.0  0.2 229308  5048 ?        S    6月11   0:00 php-fpm: pool www
    php-fpm   9257  0.0  0.2 229308  5052 ?        S    6月11   0:00 php-fpm: pool www
    php-fpm   9258  0.0  0.2 229308  5052 ?        S    6月11   0:00 php-fpm: pool www
    php-fpm   9259  0.0  0.2 229308  5052 ?        S    6月11   0:00 php-fpm: pool www
    php-fpm   9260  0.0  0.2 229308  5052 ?        S    6月11   0:00 php-fpm: pool www
    
  • 为了防止一个站点出现问题,耗尽php资源,我们应该将每个站点进行隔离,使用单独的pool,在php-fpm.conf中,可以继续添加多个pool:

    [global]
    pid = /usr/local/php-fpm/var/run/php-fpm.pid
    error_log = /usr/local/php-fpm/var/log/php-fpm.log
    [www]
    #监听地址,也可以写为127.0.0.1:9000
    #listen = /tmp/php-fcgi.sock    
    listen = 127.0.0.1:9000
    #定义socket文件的权限
    listen.mode = 666
    #定义服务启动的用户和用户组
    user = php-fpm
    group = php-fpm
    pm = dynamic
    pm.max_children = 50
    pm.start_servers = 20
    pm.min_spare_servers = 5
    pm.max_spare_servers = 35
    pm.max_requests = 500
    rlimit_files = 1024
    
    [evobot]
    listen = /tmp/php-evobot.sock
    listen.mode = 666
    user = php-fpm
    group = php-fpm
    pm = dynamic
    pm.max_children = 50
    pm.start_servers = 20
    pm.min_spare_servers = 5
    pm.max_spare_servers = 35
    pm.max_requests = 500
    rlimit_files = 1024
    
  • 然后检查配置文件正确性,重载服务,查看php-fpm进程:

    [root@evobot etc]# /usr/local/php-fpm/sbin/php-fpm -t
    [13-Jun-2018 21:19:52] NOTICE: configuration file /usr/local/php-fpm/etc/php-fpm.conf test is successful
    
    [root@evobot etc]# service php-fpm reload
    Reload service php-fpm  done
    [root@evobot etc]# ps aux | grep php
    root      1279  0.1  0.2 227284  4984 ?        Ss   21:20   0:00 php-fpm: master process (/usr/local/php-fpm/etc/php-fpm.conf)
    php-fpm   1282  0.0  0.2 229308  5060 ?        S    21:20   0:00 php-fpm: pool www
    php-fpm   1283  0.0  0.2 229308  5060 ?        S    21:20   0:00 php-fpm: pool www
    php-fpm   1284  0.0  0.2 229308  5060 ?        S    21:20   0:00 php-fpm: pool www
    php-fpm   1285  0.0  0.2 229308  5060 ?        S    21:20   0:00 php-fpm: pool www
    php-fpm   1286  0.0  0.2 229308  5064 ?        S    21:20   0:00 php-fpm: pool www
    php-fpm   1287  0.0  0.2 229308  5064 ?        S    21:20   0:00 php-fpm: pool www
    php-fpm   1288  0.0  0.2 229308  5064 ?        S    21:20   0:00 php-fpm: pool www
    php-fpm   1289  0.0  0.2 229308  5064 ?        S    21:20   0:00 php-fpm: pool www
    php-fpm   1290  0.0  0.2 229308  5064 ?        S    21:20   0:00 php-fpm: pool www
    php-fpm   1291  0.0  0.2 229308  5064 ?        S    21:20   0:00 php-fpm: pool www
    php-fpm   1292  0.0  0.2 229308  5064 ?        S    21:20   0:00 php-fpm: pool www
    php-fpm   1293  0.0  0.2 229308  5064 ?        S    21:20   0:00 php-fpm: pool www
    php-fpm   1294  0.0  0.2 229308  5068 ?        S    21:20   0:00 php-fpm: pool www
    php-fpm   1295  0.0  0.2 229308  5068 ?        S    21:20   0:00 php-fpm: pool www
    php-fpm   1296  0.0  0.2 229308  5068 ?        S    21:20   0:00 php-fpm: pool www
    php-fpm   1297  0.0  0.2 229308  5068 ?        S    21:20   0:00 php-fpm: pool www
    php-fpm   1298  0.0  0.2 229308  5068 ?        S    21:20   0:00 php-fpm: pool www
    php-fpm   1299  0.0  0.2 229308  5068 ?        S    21:20   0:00 php-fpm: pool www
    php-fpm   1300  0.0  0.2 229308  5068 ?        S    21:20   0:00 php-fpm: pool www
    php-fpm   1301  0.0  0.2 229308  5068 ?        S    21:20   0:00 php-fpm: pool www
    php-fpm   1302  0.0  0.2 229308  5060 ?        S    21:20   0:00 php-fpm: pool evobot
    php-fpm   1303  0.0  0.2 229308  5060 ?        S    21:20   0:00 php-fpm: pool evobot
    php-fpm   1304  0.0  0.2 229308  5060 ?        S    21:20   0:00 php-fpm: pool evobot
    php-fpm   1305  0.0  0.2 229308  5060 ?        S    21:20   0:00 php-fpm: pool evobot
    php-fpm   1306  0.0  0.2 229308  5064 ?        S    21:20   0:00 php-fpm: pool evobot
    php-fpm   1307  0.0  0.2 229308  5064 ?        S    21:20   0:00 php-fpm: pool evobot
    php-fpm   1308  0.0  0.2 229308  5064 ?        S    21:20   0:00 php-fpm: pool evobot
    php-fpm   1309  0.0  0.2 229308  5064 ?        S    21:20   0:00 php-fpm: pool evobot
    php-fpm   1310  0.0  0.2 229308  5068 ?        S    21:20   0:00 php-fpm: pool evobot
    php-fpm   1311  0.0  0.2 229308  5068 ?        S    21:20   0:00 php-fpm: pool evobot
    php-fpm   1313  0.0  0.2 229308  5068 ?        S    21:20   0:00 php-fpm: pool evobot
    php-fpm   1314  0.0  0.2 229308  5068 ?        S    21:20   0:00 php-fpm: pool evobot
    php-fpm   1315  0.0  0.2 229308  5068 ?        S    21:20   0:00 php-fpm: pool evobot
    php-fpm   1316  0.0  0.2 229308  5068 ?        S    21:20   0:00 php-fpm: pool evobot
    php-fpm   1317  0.0  0.2 229308  5068 ?        S    21:20   0:00 php-fpm: pool evobot
    php-fpm   1318  0.0  0.2 229308  5068 ?        S    21:20   0:00 php-fpm: pool evobot
    php-fpm   1319  0.0  0.2 229308  5068 ?        S    21:20   0:00 php-fpm: pool evobot
    php-fpm   1320  0.0  0.2 229308  5068 ?        S    21:20   0:00 php-fpm: pool evobot
    php-fpm   1321  0.0  0.2 229308  5068 ?        S    21:20   0:00 php-fpm: pool evobot
    php-fpm   1322  0.0  0.2 229308  5068 ?        S    21:20   0:00 php-fpm: pool evobot
    root      1329  0.0  0.0 112676   980 pts/1    R+   21:20   0:00 grep --color=auto php
    

    可以看到在进程中多了evobot的pool。

  • 在Nginx中为不同的虚拟主机使用不同的php-fpm的pool,则需要修改虚拟主机配置文件,将其中的php配置的fastcgi_pass更改为指定的pool的socket路径:

     location ~ \.php$
        {
            include fastcgi_params;
            fastcgi_pass unix:/tmp/evobot.sock;
            fastcgi_index index.php;
            fastcgi_param SCRIPT_FILENAME /data/wwwroot/auth.evobot.cn$fastcgi_script_name;
        }
    

    这样对虚拟主机的php进行区分,可以防止一个虚拟主机访问量过大导致php资源耗尽报502错误时,不影响其他的虚拟主机运行。

  • 在nginx.conf配置中,我们指定虚拟主机配置使用了incluede vhost/*conf;这样的配置来让nginx能够支持多个虚拟主机配置,同样的php-fpm也支持多个不同pool的配置文件,让不同的pool的配置独立到不同的配置文件中,这样的配置只需要在php-fpm.conf文件的[global]配置下,加入下面的配置:

    include = etc/php-fpm.d/*.conf
    
    [global]
    pid = /usr/local/php-fpm/var/run/php-fpm.pid
    error_log = /usr/local/php-fpm/var/log/php-fpm.log
    include = etc/php-fpm.d/*.conf
    
  • 然后在/usr/local/php-fpm/etc目录下创建php-fpm.d目录,将php-fpm.conf配置文件中的两个pool分别写入到独立的配置文件中,并存放于php-fpm.d目录下:

    创建www.conf:

    [www]
    #监听地址,也可以写为127.0.0.1:9000
    #listen = /tmp/php-fcgi.sock    
    listen = 127.0.0.1:9000
    #定义socket文件的权限
    listen.mode = 666
    #定义服务启动的用户和用户组
    user = php-fpm
    group = php-fpm
    pm = dynamic
    pm.max_children = 50
    pm.start_servers = 20
    pm.min_spare_servers = 5
    pm.max_spare_servers = 35
    pm.max_requests = 500
    rlimit_files = 1024
    

    创建evobot.conf:

    [evobot]
    listen = /tmp/php-evobot.sock
    listen.mode = 666
    user = php-fpm
    group = php-fpm
    pm = dynamic
    pm.max_children = 50
    pm.start_servers = 20
    pm.min_spare_servers = 5
    pm.max_spare_servers = 35
    pm.max_requests = 500
    rlimit_files = 1024
    
  • 然后重新检查配置文件正确性并重载服务,与之前的配置效果相同。

php-fpm慢执行日志

  • 有时候网站访问会比较慢,如果是系统负载引起的,我们可以使用各种命令行工具查看CPU、磁盘负载等等来找出导致负载高的进程,但如果是网站的代码导致的访问慢,如php代码层面的问题,那么配置慢执行日志,对我们排查问题将会非常有用;

  • 慢执行日志需要在pool中配置以下配置项:

    request_slowlog_timeout = 1
    slowlog = /usr/local/php-fpm/var/log/www-slow.log
    

    配置完成后的pool配置如下:

    [www]
    listen = 127.0.0.1:9000
    listen.mode = 666
    user = php-fpm
    group = php-fpm
    pm = dynamic
    pm.max_children = 50
    pm.start_servers = 20
    pm.min_spare_servers = 5
    pm.max_spare_servers = 35
    pm.max_requests = 500
    rlimit_files = 1024
    request_slowlog_timeout = 1
    slowlog = /usr/local/php-fpm/var/log/www-slow.log
    
  • 重新加载配置和服务,可以在定义的slowlog路径中查看慢执行日志:

    [root@evobot etc]# cat /usr/local/php-fpm/var/log/www-slow.log 
    
  • 由于没用执行慢于1秒的php,所以暂时日志里没有内容,测试慢日志,可以创建一个php文件,写入以下内容:

    <?php
    echo "test slow log";
    sleep(2);
    echo "done";
    ?>
    
  • 然后进行访问,如果出现错误,可以在php.ini中将display_errors = Off改为On,然后可以在浏览器中查看出错的原因。访问上面的php,然后查看慢日志如下:

    [root@evobot etc]# cat ../var/log/www-slow.log 
    
    [13-Jun-2018 22:19:41]  [pool www] pid 3992
    script_filename = /data/wwwroot/auth.evobot.cn/slow.php
    [0x00007f436d5826c8] sleep() /data/wwwroot/auth.evobot.cn/slow.php:3
    

    可以看到日志中记录了哪一条语句执行超过了1秒,导致了加载缓慢。一般实际使用中会将慢执行日志的配置设置为2秒。

open_basedir

  • 这里的open_basedir与LAMP中相同,都是为了防止站点出现安全问题时影响到其他的虚拟主机,我们可以针对每个pool定义其open_basedir,在pool的配置中,写入以下配置:

    php_admin_value[open_basedir]=/data/wwwroot/auth.evobot.cn:/tmp/
    

    pool的完整配置如下:

    [www]
    listen = 127.0.0.1:9000
    listen.mode = 666
    user = php-fpm
    group = php-fpm
    pm = dynamic
    pm.max_children = 50
    pm.start_servers = 20
    pm.min_spare_servers = 5
    pm.max_spare_servers = 35
    pm.max_requests = 500
    rlimit_files = 1024
    request_slowlog_timeout = 1
    slowlog = /usr/local/php-fpm/var/log/www-slow.log
    php_admin_value[open_basedir]=/data/wwwroot/auth.evobot.cn:/tmp/
    

    这里php还需要访问tmp目录的socket,所以要加上tmp目录在配置中。

  • 重新加载配置文件和重载php-fpm服务之后生效,如果open_basedir配置错误,访问站点会报错。

  • 在php.ini中,配置错误日志,首先将log_errors置为On,然后将error_reporting设置为需要的日志级别,如E_ALL,最后配置error_log,指定日志存放路径:

    log_errors = On
    error_reporting = E_ALL
    error_log = /usr/local/php-fpm/var/log/php_errors.log
    
  • 接着将虚拟主机使用的pool的open_basedir改为错误,进行访问并查看日志:

    php_admin_value[open_basedir]=/data/wwwroot/default:/tmp/
    
    
    [root@evobot etc]# curl -x127.0.0.1:80 auth.evobot.cn/index.php
    No input file specified.
    
    [root@evobot etc]# cat ../var/log/php_error.log
    [14-Jun-2018 09:11:26 UTC] PHP Warning:  Unknown: open_basedir restriction in effect. File(/data/wwwroot/test/index.php) is not within the allowed path(s): (/data/wwwroot/test2:/tmp/) in Unknown on line 0
    [14-Jun-2018 09:11:26 UTC] PHP Warning:  Unknown: failed to open stream: Operation not permitted in Unknown on line 0
    [14-Jun-2018 09:12:14 UTC] PHP Warning:  Unknown: open_basedir restriction in effect. File(/data/wwwroot/test/index.php) is not within the allowed path(s): (/data/wwwroot/test2:/tmp/) in Unknown on line 0
    [14-Jun-2018 09:12:14 UTC] PHP Warning:  Unknown: failed to open stream: Operation not permitted in Unknown on line 0
    

    如果出现日志无法记录的情况,要检查phpinfo中php.ini文件的位置,以及是否加载了php.ini配置文件。

php-fpm进程管理

  • 在pool的配置中,都有这样一段配置:

    pm = dynamic
    pm.max_children = 50
    pm.start_servers = 20
    pm.min_spare_servers = 5
    pm.max_spare_servers = 35
    pm.max_requests = 500
    
    
  • 这里pm = dynamic表示动态启动和销毁子进程,也可以定义为static,直接一次启动所有的子进程,并且pm.max_children=50下面的配置都不会再生效。

  • pm.max_children = 50表示最大子进程数,php会在子进程数内动态启动、销毁子进程,但销毁子进程是有限度的,最低要保留5个子进程;

  • pm.start_servers = 20则表示启动服务时会启动的进程数;

  • pm.min_spare_servers = 5则定义了在空闲时段,子进程数的最少数量,如果达到这个数值,那么php-fpm服务会自动派生新的子进程;

  • pm.max_spare_servers = 35定义了在空闲时段,子进程数的最大数量,如果高于这个数值,那么php-fpm就会开始清理空闲的子进程;

  • pm.max_requests = 500则定义了一个子进程最多处理的请求数,即一个php-fpm的子进程可以处理这么多请求,当达到这个数值时,子进程就会自动退出。