美文网首页PHP
php-fpm入门简介(1)

php-fpm入门简介(1)

作者: 冬日大草原的黄昏 | 来源:发表于2019-06-28 14:25 被阅读0次

    php-fpm

    应用场景

    php-fpm是个中间件,在需要php解释器来处理.php文本时会用到php-fpm。自从php5.3.3以后就将php-fpm集成在php内核中。PHP-FPM提供了更好的PHP进程管理方式,可以有效控制内存和进程、可以平滑重载PHP配置。

    相关概念

    1.CGI

    CGI(common gateway interface )通用网关接口,是webserver和web应用程序交流时的一组接口规范。

    2.Fast-cgi

    FastCGI可以理解为一种协议,用于web服务器(nginx,Apache)和处理程序间进行通信,是一种应用层通信协议。是cgi协议的升级版

    fast-cgi每次处理完请求后,不会kill掉这个进程,而是保留这个进程,使这个进程可以一次处理多个请求。这样每次就不用重新fork一个进程了,从而避免了每个请求进程创建和终止的开销,大大提高了效率。

    3.Php-cgi

    php-cgi是一个进程。php-cgi实现了cgi这种协议,但是它是单进程的,一个进程处理一个请求,处理结束后进程就自我销毁。

    4.Php-fpm

    是对php-cgi的改进版,它直接管理多个php-cgi进程/线程。也就是说,php-fpm是php-cgi的进程管理器,因此它算是fastcgi协议的实现。在一定程度上讲,php-fpm与php的关系,和tomcat对java的关系是类似的.

    5.cgi进程/线程:

    在php上,就是php-cgi进程/线程。专门用于接收web server的动态请求,调用并初始化zend虚拟机。

    6.cgi脚本:

    被执行的php源代码文件。

    7.zend虚拟机:

    对php文件做词法分析、语法分析、编译成opcode,并执行。最后关闭zend虚拟机。

    8.cgi进程/线程和zend虚拟机的关系:

    cgi进程调用并初始化zend虚拟机的各种环境。

    9、cgi、fastcgi、php-cgi和php-fpm之间的关系

    1.png

    未出现php-fpm之前

    web server对cgi进程/线程来说,它的作用就是发起动态处理请求,传递一些参数和环境变量,最后接收cgi的返回结果。通俗点说就是当接收到一个请求时,webserver临时启动一个cgi解释器,并通过cgi协议转发要运行的内容。当cgi脚本运行结束后,将结果返回给webserver,然后cgi解释器进程自我销毁。假如有10000个请求进来,那么就会先后启动10000个cgi解释器,这种方法效率极低。

    php-fpm工作原理

    php-fpm的管理对象是php-cgi进程

    2.png

    1.master进程

    php-fpm是一种多进程的模型,由一个master进程和若干worker进程组成(具体数量需要看php-fpm.conf的配置),master不会处理请求,而是fork出worker子进程去接受和处理请求

    master进程的主要作用就是管理worker进程,负责fork或者kill掉子进程。在启动时根据配置文件会预先启动一定数量的php-fpm进程。当请求比较多worker处理不过来时,master会fork新的worker进程处理。如果空闲的进程较多时,就会kill掉一些worker进程,避免占用浪费系统资源。

    2.worker进程

    worker进程的主要工作是处理请求,每个worker进程都会accept请求,接受成功后会解析fastcgi,然后执行脚本,完成后关闭请求,继续等待新的连接。

    安装php-fpm

    1.安装php运行环境

    下载php-7.1.26.tar.gz

    wget http://cn2.php.net/get/php-7.1.26.tar.gz/from/this/mirror

    2.因为php安装需要编译,所以服务器应该保证gcc和g++环境的安装

    yum -y install libxml2
    yum -y install libxml2-devel
    yum -y install openssl
    yum -y install openssl-devel
    yum -y install curl
    yum -y install curl-devel
    yum -y install libjpeg
    yum -y install libjpeg-devel
    yum -y install libpng
    yum -y install libpng-devel
    yum -y install freetype
    yum -y install freetype-devel
    yum -y install pcre
    yum -y install pcre-devel
    yum -y install libxslt
    yum -y install libxslt-devel
    yum -y install bzip2
    yum -y install bzip2-devel
    yum -y install gcc gcc-c++
    

    3。php7中,对lib-zip和cmake版本要求较高,编译时可能会由于版本过低导致编译错误,需要手动编译源码包解决,这里下载libzip-1.5.1.tar.gz和cmake-3.13.4.tar.gz

    wget  https://github.com/Kitware/CMake/releases/download/v3.13.4/cmake-3.13.4.tar.gz
    tar xvf cmake-3.13.4.tar.gz && cd cmake-3.13.4/
    ./bootstrap
    gmake
    gmake install
    
    wget  https://libzip.org/download/libzip-1.5.1.tar.gz
    tar -xvzf libzip-1.5.1.tar.gz 
    cd  libzip-1.5.1
    mkdir build && cd build/
    cmake -DCMAKE_INSTALL_PREFIX=/usr/local/libzip ..
    make
    make install
    

    4.配置参数,添加--enable-fpm参数(nginx编译时应添加ngx_http_fastcgi_module模块)

    ./configure --prefix=/usr/local/php \
    --with-curl \
    --with-freetype-dir \
    --with-gd \
    --with-gettext \
    --with-iconv-dir \
    --with-kerberos \
    --with-libdir=lib64 \
    --with-libxml-dir \
    --with-mysqli \
    --with-openssl \
    --with-pcre-regex \
    --with-pdo-mysql \
    --with-pdo-sqlite \
    --with-pear \
    --with-png-dir \
    --with-jpeg-dir \
    --with-xmlrpc \
    --with-xsl \
    --with-zlib \
    --with-bz2 \
    --with-mhash \
    --enable-fpm \
    --enable-bcmath \
    --enable-libxml \
    --enable-inline-optimization \
    --enable-mbregex \
    --enable-mbstring \
    --enable-opcache \
    --enable-pcntl \
    --enable-shmop \
    --enable-soap \
    --enable-sockets \
    --enable-sysvsem \
    --enable-sysvshm \
    --enable-xml \
    --enable-zip \
    --with-libzip=/usr/local/libzip
    

    5.执行编译

    make && make install
    

    6.配置文件

    cp php.ini-development /usr/local/php/lib/php.ini
    cp /usr/local/php/etc/php-fpm.conf.default /usr/local/php/etc/php-fpm.conf
    cp sapi/fpm/php-fpm /usr/local/sbin
    

    注:

    php-fpm.conf是PHP-FPM特有的配置文件

    php.ini是所以php模式中必须的配置文件,对php的整体环境配置起作用

    两者的区别是,php-fpm.conf是PHP-FPM进程管理器的配置文件,php.ini是PHP解析的配置文件

    7.PHP-FPM 主配置文件 /usr/local/php/etc/php-fpm.conf

    [global]
    pid = /var/run/php-fpm.pid
    error_log = /var/log/php-fpm.log
    process_control_timeout = 0
    ;动态方式下开启的php-fpm进程的最大数量
    process.max = 10   (此值会影响到poll的最大进程数,以这里的数值为准,或者注释掉在pool里配置)
    ;设置 fpm 在后台运行
    daemonize = yes
    ; 设置进程可以打开的文件描述符数量
    rlimit_files = 65535
    ; 设置FPM 的事件处理机制
    events.mechanism = epoll
    ;emergency_restart_interval所设值内出现SIGSEGV或者SIGBUS错误的php-cgi进程数如果超过 emergency_restart_threshold个,php-fpm就会优雅重启
    emergency_restart_threshold = 10(个)
    emergency_restart_interval = 5(s)
    ;  加载pool 配置
    include = /usr/local/php/etc/php-fpm.d/*.conf
    

    注:

    1.SIGBUS(Bus error)意味着指针所对应的地址是有效地址,但总线不能正常使用该指针。通常是未对齐的数据访问所致。

    2.SIGSEGV(Segment fault)意味着指针所对应的地址是无效地址,没有物理内存对应该地址。

    8.创建用户和组

    useradd aaa groupadd aaa
    

    9.配置子配置文件(pool池)

    vim /usr/local/php/etc/php-fpm.d/aaa.conf
    
    [aaa.com]
    user = aaa
    group = aaa
    listen = 127.0.0.1:9000
    ;允许访问FastCGI进程的IP,设置any为不限制IP,如果要设置其他主机的nginx也能访问这台FPM进程,listen处要设置成本地可被访问的IP。默认值是any。每个地址是用逗号分隔. 如果没有设置或者为空,则允许任何服务器请求连接
    listen.allowed_clients = 127.0.0.1
    ; 如何控制子进程,选项有static、dynamic和ondemand。如果选择static,则由pm.max_children指定固定的子进程数。ondemand: 按需分配,当收到用户请求时fork worker进程。 如果选择ondemand,按需分配,当收到用户请求时fork worker进程。如果选择dynamic,则由以下参数决定:
    pm = dynamic
    pm.max_children = 10
    pm.start_servers = 5
    pm.min_spare_servers = 3
    pm.max_spare_servers = 8
    ; 设置每个进程可处理的请求数,当进程达到这个请求数量后会自动释放在重新生成新的进程。避免内存泄漏等情况
    pm.max_requests = 15 
    ; FPM 的监控设置
    pm.status_path = /status
    ; 终止请求超时时间。一个请求若处理大于20s ,则会自动kill 掉。避免进程堆积
    request_terminate_timeout = 20
    catch_workers_output = no
    ; 限制 FPM 允许解析的脚本扩展名. 这里不限制,FPM可以解析任何扩展名的文件
    security.limit_extensions = ""
    

    注:

    pm.max_requests = 15 ,这段配置的意思是,当一个 PHP-CGI 进程处理的请求数累积到 15个后,自动重启该进程。如果设置为 '0' 则一直接受请求. 等同于 PHP_FCGI_MAX_REQUESTS 环境变量. 默认值: 0.

    为什么要重启呢?

    一般在项目中,我们多多少少都会用到一些 PHP 的第三方库,这些第三方库经常存在内存泄漏问题,如果不定期重启 PHP-CGI 进程,势必造成内存使用量不断增长。因此 PHP-FPM 作为 PHP-CGI 的管理器,提供了这么一项监控功能,对请求达到指定次数的 PHP-CGI 进程进行重启,保证内存使用量不增长。

    10.配置nginx

     server {
            listen       80;
            server_name  aaa.com;
          location / {
                root   html;
                index  index.html index.htm;
            }
            error_page   500 502 503 504  /50x.html;
            location = /50x.html {
                root   html;
            }
          location ~ /status {
                 include fastcgi.conf;
                 fastcgi_pass 127.0.0.1:9000;
        }
    
           location ~ /ping {
                include fastcgi.conf;
                fastcgi_pass 127.0.0.1:9000;
        }
            location ~ \.php$ {
                root           html;
                fastcgi_pass   127.0.0.1:9000;
                fastcgi_index  index.php;
                fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
                include        fastcgi_params;
            }
            }
        }
    

    11.启动php-fpm,默认端口为9000.

    /usr/local/php/sbin/php-fpm
    

    开启php-fpm监控功能

    /usr/local/php/etc/php-fpm.d/aaa.conf
    
    3.png

    注:这里斜杠后的status是可以自定义的,在nginx上location上配置匹配的选项即可。

    如下

    4.png

    验证动态模式下开启的进程数

    5.png

    查看php-fpm状态参数

    curl 192.168.112.111/status

    6.png

    相应参数解释

    # PHP-FPM 的POOL名字
    pool:                 aaa.com
    # 这个POOL中进程管理方式,这里是动态管理方式。相反还有静态管理方式。
    process manager:      dynamic
    # POOL从什么时间开始启动
    start time:          09/Mar/2019:21:02:43 +0800
    # POOL 从启动到现在已经存活了多久
    start since:         779   (单位秒)
    # 当前POOL接受的请求数
    accepted conn:        1
    # 请求等待队列当前长度,如果这个值不为0,那么说明你的请求处理已经开始有挤压了,应该注意系统状态。
    listen queue:         0
    # 从启动到现在,请求等待队列历史最大长度
    max listen queue:     0
    # 请求队列长度大小
    listen queue len:     128
    # 目前空闲进程数
    idle processes:       4
    # 目前工作进程数
    active processes:     1
    # 目前总进程数
    total processes:      5
    # 从启动到现在,最大的活跃进程数量
    max active processes: 1
    # 达到进程最大数量限制的次数,如果这个数量不为0,那说明设置的最大进程数量(pm.max_children)太小了,或者进程积压了。
    max children reached: 0
    # 慢请求的数量
    slow requests:        0
    

    总结

    nginx与php-fpm的完整流程是这样的


    image.png

    如图,简单版的cgi工作方式

    7.png

    默认虚拟主机

    默认虚拟主机就是配置文件里的第一个虚拟主机。关于默认虚拟主机有个特点,凡是解析到这台机器的域名,不管是什么域名,只要在配置文件中没有配置,那么都会访问到这个虚拟主机上来。也就是说默认虚拟主机是一个兜底的虚拟主机。

    php-fpm的三种运行模式

    php-fpm支持三种运行模式,分别为static、ondemand、dynamic,默认为dynamic 。

    static: 静态模式,启动时分配固定的worker进程。

    ondemand: ondemand: 按需分配,当收到用户请求时fork worker进程,也就是说最初系统不会启动php-fpm进程,当有连接进来时按需启动。

    dynamic: 动态模式,启动时分配固定的进程。伴随着请求数增加,在设定的浮动范围调整worker进程

    验证

    1.static模式

    在/usr/local/php/etc/php-fpm.d/aaa.conf里配置运行模式为static,并配置最大开启的进程数为30.如图:

    8.png

    重启php-fpm,查看php-fpm进程数量

    ps -ef |grep php-fpm
    
    9.png

    可以看到,当配置文件里设置php-fpm的运行方式为static模式时,启动的php-fpm进程数只受pm.max_children 这个参数值的影响,与其他的参数值无关。

    2.ondemand模式

    修改配置文件aaa.conf,配置为ondemand模式,与其相关的两个参数是pm.max_children 和 pm.process_idle_timeout , pm.process_idle_timeout 表示系统检测到php-fpm进程的空闲时间(秒)达到规定值时就会将其会kill。如下:

    修改完成后启动php-fpm,查看进程数如下:

    11.png

    可以看到php-fpm的master启动时,并没有fork出子进程。

    通过curl去测试访问

    curl 192.168.112.111/test.php
    

    再次查看进程数,可以看到已经有一个php-fpm进程启动。

    12.png

    在配置文件里写到php-fpm进程空闲15s后将会被masterkill掉,这里可以等待15s左右再去查看进程数,如下图,可以看到该进程已经被kill掉。

    13.png

    动态模式在前文已做验证,这里不再叙述。

    版权申明:欢迎转载,但请注明出处
    一些博文中有一些参考内容因时间久远找不到来源了没有注明,如果侵权请联系我删除。

    相关文章

      网友评论

        本文标题:php-fpm入门简介(1)

        本文链接:https://www.haomeiwen.com/subject/siemoqtx.html