记录一次线上服务器内存持续增高问题梳理及总结

1、问题现象

11.png

2、项目背景

  1. 线上web服务是nginx+php7+mysql
  2. 线上服务器配置:8核16G
  3. php-fpm配置:php

    pm = static
    pm.max_children = 500
    ;pm.max_requests = 5000 //此配置没有打开

3、内存持续增高缘由分析

  1. 查看了php-fpm相关配置后,发现系统是静态机制,而且没有配置max_requests项,没有退出机制
  2. php进程长期存在致使内存积压没法释放,因此内存消耗持续升高
  3. nginx+php-fpm运行原理?【https://juejin.im/post/58db7d...html

    cgi、fast-cgi、php-fpm之间的关系?
    
    个人理解:
        1.webserver最开始只能处理静态请求,后来出现了动态请求,好比php程序,然而webserver是没法处理php程序的,这个是时候怎么办?
        2.交给php解释器来处理动态php请求
        3.那么webserver能够将动态请求交给php解释器处理,那么webserver如何与php解释器进行通讯呢?【webserver就是nginx/apache】
        4.这个时候就出现了cgi,cgi协议就是webserver和php解释器进行通讯的协议
        5.webserver在每次请求过来都会fork一个cgi进程进行处理,处理完成后返回,若是有10k请求,那么就fork 10k个进程,显然对系统资源很浪费
        6.这时对cgi作了优化,出现了fast-cgi,fast-cgi在请求处理完成后不会直接kill掉这个进程,而是继续保留请求下一次请求,这样一个进程就能处理多个请求,不用每次都fork进程减小了系统资源浪费
        7.而php-fpm就是fast-cgi的实现,而且提供了进程管理的功能,包含master和worker两种类型的进程
        8.master进程只负责监听端口,接收来自webserver的请求,worker进程有多个,每一个worker进程内部都嵌入了一个php解释器,是php代码真正执行的地方
  4. 一些php-fpm参数理解:mysql

    pm = dynamic # 三种类型选择,static/dynamic/ondemand
    pm.max_children = 5 # php-fpm的worker进程最大数量
    pm.start_servers = 3 # php-fpm启动时候,启动的worker数量
    pm.min_spare_servers = 2 # php-fpm最小空闲进程数量,每时每刻最少也有2个是空闲的进程
    pm.max_spare_servers = 4 # php-fpm最大的空闲进程数量
    pm.max_requests = 200 # 单个进程处理请求数量达到200就会kill掉该进程重启,进程一直存活容易发生内存泄漏

4、解决方案

  1. 经过如今php-fpm的配置能够得知,php-fpm没有设置max_requests,表明进程一直不会退出,每一个请求完成后php-cgi会回收内存,可是不会释放给操做系统,因此大量内存被php-cgi占用。
  2. 官方的解决办法就是下降PHP_FCGI_MAX_REQUESTS的值,对应php-fpm配置中的max_requests
  3. 因此,只要从新设置 max_requests 的值,让进程达到这个值后自动重启释放内存便可nginx

    # php-fpm.conf配置
    pm = static
    pm.max_children = 500
    pm.start.servers = 100
    pm.min_spare_servers = 20
    pm.max_spare_servers = 100
    pm.max_requests = 2000
  4. 修改完配置后对php-fpm进行重启web

    //查询当前fpm的master进程号
    ps aux|grep php-fpm | grep master
    //平滑重启fpm,42891是master进程号
    kill -USR2 42891
    //当即终止fpm
    kill -QUIT 42891
    //查看状态
    ps aux|grep php-fpm
      
      
    //备注:
    php 5.3.3 之后的php-fpm 再也不支持 php-fpm 之前具备的 /usr/local/php/sbin/php-fpm (start|stop|reload)等命令,因此不要再看这种老掉牙的命令了,须要使用信号控制:
     
    master进程能够理解如下信号
     
    INT, TERM 马上终止
    QUIT 平滑终止
    USR1 从新打开日志文件
    USR2 平滑重载全部worker进程并从新载入配置和二进制模块
  5. 参考:https://www.cnblogs.com/cocol...
相关文章
相关标签/搜索