wudanyang

wudanyang 查看完整档案

北京编辑山东建筑大学  |  计算机科学与技术 编辑  |  填写所在公司/组织 wdy1184.com 编辑
编辑

danyang

个人动态

wudanyang 赞了文章 · 1月7日

php-fpm进程数管理

PHP-FPM

先来了解一些名词概念:

CGICommon Gateway Interface(通用网管协议),用于让交互程序和Web服务器通信的协议。它负责处理URL的请求,启动一个进程,将客户端发送的数据作为输入,由Web服务器收集程序的输出并加上合适的头部,再发送回客户端。

FastCGI是基于CGI的增强版本的协议,不同于创建新的进程来服务请求,使用持续的进程和创建的子进程来处理一连串的进程,这些进程由FastCGI服务器管理,开销更小,效率更高。

PHP-FPMPHP实现的FastCGI Process Manager(FastCGI进程管理器), 用于替换PHP FastCGI的大部分附加功能,适用于高负载网站。支持的功能如:

  1. 平滑停止/启动的高级进程管理功能
  2. 慢日志记录脚本
  3. 动态/静态子进程产生
  4. 基于php.ini的配置文件

PHP-FPM在5.4之后已经整合进入PHP源代码中,提供更好的PHP进程管理方式,可以有效控制内存和进程,平滑重载PHP配置。如果需要使用,在./configure的时候带上-enable-fpm参数即可,使用PHP-FPM来控制FastCGI进程:

// 支持start/stop/quit/restart/reload/logrotate参数
// quit/reload是平滑终止和平滑重新加载,即等现有的服务完成
./php-fpm --start

PHP-FPM 配置

PHP-FPM配置文件为php-fpm.conf,在这个配置文件中我们需要了解一些参数。下面所有的子进程均指php-fpm进程,可以在终端通过ps aux | grep php查看到。

  • 显示php-fpm: pool www的代表work子进程(实际处理请求)
  • 显示php-fpm: process master的代表master主进程(负责管理work子进程)

全局配置

先看PHP-FPM最重要的全局配置部分:

emergency_restart_threshold

如果在emergency_restart_interval设定的时间内收到该参数设定次数的SIGSEGVSIGBUS退出的信号,则FPM会重新启动。默认值为0,表示关闭该功能。

emergency_restart_interval

设定平滑重启的间隔时间,有助于解决加速器中共享内存的使用问题。可用单位s(默认)/m/h/d,默认值为0, 表示关闭。

process.max

FPM能够创建的最大子进程数量,它在使用多个pm = dynamic配置的php-fpm pool进程池的时候,控制全局的子进程数量。默认值为0,代表着无限制。

进程池配置

PHP-FPM的配置其余部分是一个名为Pool Definitions的区域,这个区域的配置设置每个PHP-FPM进程池,进程池中是一系列相关的子进程。这部分开头都是[进程池名称],如[www]

此时可以解释看到ps aux | grep php中显示的是php-fpm: pool www

pm

pm指的是process manager,指定进程管理器如何控制子进程的数量,它为必填项,支持3个值:

  • static: 使用固定的子进程数量,由pm.max_children指定
  • dynamic:基于下面的参数动态的调整子进程的数量,至少有一个子进程

    • pm.max_chidren: 可以同时存活的子进程的最大数量
    • pm.start_servers: 启动时创建的子进程数量,默认值为min_spare_servers + max_spare_servers - min_spare_servers) / 2
    • pm.min_spare_servers: 空闲状态的子进程的最小数量,如果不足,新的子进程会被自动创建
    • pm.max_spare_servers: 空闲状态的子进程的最大数量,如果超过,一些子进程会被杀死
  • ondemand: 启动时不会创建子进程,当新的请求到达时才创建。会使用下面两个参数:

    • pm.max_children
    • pm.process_idle_timeout 子进程的空闲超时时间,如果超时时间到没有新的请求可以服务,则会被杀死

pm.max_requests

每一个子进程的最大请求服务数量,如果超过了这个值,该子进程会被自动重启。在解决第三方库的内存泄漏问题时,这个参数会很有用。默认值为0,指子进程可以持续不断的服务请求。

PHP-FPM配置优化

PHP-FPM管理的方式是一个master主进程,多个pool进程池,多个worker子进程。其中每个进程池监听一个socket套接字。具体的图示:

图片描述

其中的worker子进程实际处理连接请求,master主进程负责管理子进程:

1. `master`进程,设置1s定时器,通过`socket`文件监听
2. 在`pm=dynamic`时,如果`idle worker`数量<`pm.min_spare_servers`,创建新的子进程
3. 在`pm=dynamic`时,如果`idle worker`数量>`pm.max_spare_servers`,杀死多余的空闲子进程
4. 在`pm=ondemand`时,如果`idle worker`空闲时间>`pm.process_idle_timeout`,杀死该空闲进程
5. 当连接到达时,检测如果`worker`数量>`pm.max_children`,打印`warning`日志,退出;如果无异常,使用`idle worker`服务,或者新建`worker`服务

保障基本安全

我们为了避免PHP-FPM主进程由于某些糟糕的PHP代码挂掉,需要设置重启的全局配置:

; 如果在1min内有10个子进程被中断失效,重启主进程
emergency_restart_threshold = 10
emergency_restart_interval = 1m

进程数调优

每一个子进程同时只能服务一次连接,所以控制同时存在多少个进程数就很重要,如果过少会导致很多不必要的重建和销毁的开销,如果过多又会占用过多的内存,影响其他服务使用。

我们应该测试自己的PHP进程使用多少内存,一般来说刚启动时是8M左右,运行一段时间由于内存泄漏和缓存会上涨到30M左右,所以你需要根据自己的预期内存大小设定进程的数量。同时根据进程池的数量来看一个进程管理器的子进程数量限制。

测试平均PHP子进程占用的内存:

$ps auxf | grep php | grep -v grep
work     26829  0.0  0.0 715976  4712 ?        Ss   Jul11   0:00 php-fpm: master process (./etc/php-fpm.conf)
work     21889  0.0  0.0 729076 29668 ?        S    03:12   0:20  \_ php-fpm: pool www         
work     21273  0.0  0.0 728928 31380 ?        S    03:25   0:21  \_ php-fpm: pool www         
work     15114  0.0  0.0 728052 29084 ?        S    03:40   0:19  \_ php-fpm: pool www         
work     17072  0.0  0.0 728800 34240 ?        S    03:54   0:22  \_ php-fpm: pool www         
work     22763  0.0  0.0 727904 20352 ?        S    11:29   0:04  \_ php-fpm: pool www         
work     38545  0.0  0.0 727796 19484 ?        S    12:34   0:01  \_ php-fpm: pool www

// 共占用的内存数量
$ps auxf | grep php | grep -v grep | grep -v master | awk '{sum+=$6} END {print sum}'
162712

// 所有的子进程数量
$ ps auxf | grep php | grep -v grep | grep -v master | wc -l 
6

可以看到第6列,每一个子进程的内存占用大概在19-34M之间(单位为KB)。平均的内存占用为162712KB/6 = 27.1M

查看服务器总的内存大小

$ free -g
             total       used       free     shared    buffers     cached
Mem:           157        141         15          0          4        123
-/+ buffers/cache:         13        143
Swap:            0          0          0

可以看出我的服务器总得内存大小是157G(-g采用了G的单位)。

进程数限制

此时如果我们分配全部的内存给PHP-FPM使用,那么进程数可以限制在157000/27 = 5814,但是由于我的服务器同时服务了很多内容,所以我们可以向下调整到512个进程数:

process.max = 512
pm = dynamic
pm.max_children = 512
pm.start_servers = 16
pm.min_spare_servers = 8
pm.max_spare_serveres = 30

防止内存泄漏

由于糟糕的插件和库,内存泄漏时有发生,所以我们需要对每一个子进程服务的请求数量做限制,防止无限制的内存泄漏:

pm.max_requests = 1000

重启

如果上面的配置都按照你的实际需求和环境配置好了,不要忘记重启PHP-FPM服务。

参考资料

  1. PHP手册-FastCGI: http://php.net/manual/zh/inst...
  2. 维基百科-CGI:https://zh.wikipedia.org/wiki...
  3. 维基百科-FastCGI:https://zh.wikipedia.org/wiki...
  4. 博客园 php-fpm进程数优化:https://www.cnblogs.com/52fhy...
  5. 简书 php-fpm进程管理:https://www.jianshu.com/p/c9a...
  6. PHP手册 php-fpm.conf:http://php.net/manual/zh/inst...
  7. 《Modern PHP》 第七章 PHP-FPM
查看原文

赞 54 收藏 51 评论 8

wudanyang 关注了用户 · 2019-12-29

LNMPR源码研究 @php7internal

一群热爱代码的人 研究Nginx PHP Redis Memcache Beanstalk 等源码 以及一群热爱前端的人
希望交流的朋友请加微信 289007301 注明:思否 拉到交流群

《PHP7底层设计与源码分析》勘误https://segmentfault.com/a/11...

《Redis5命令设计与源码分析》https://item.jd.com/12566383....

景罗 陈雷 李乐 黄桃 施洪宝 季伟滨 闫昌 李志 王坤 肖涛 谭淼 张仕华 方波 周生政 熊浩含 张晶晶(女) 李长林 朱栋 张晶晶(男) 陈朝飞 巨振声 杨晓伟 闫小坤 韩鹏 夏达 周睿 李仲伟 张根红 景罗 欧阳 孙伟 李德 twosee

关注 4310

wudanyang 赞了文章 · 2019-08-02

codeception (3)在yii2下创建Unit Tests (单元测试)

我们为frontend的登陆建立一个单元测试
图片描述
提示创建成功,路径写也出来了,我们打开看一下这个文件列表
图片描述
打开生成的文件

namespace tests\codeception\frontend;
class ApiLoginTest extends \Codeception\TestCase\Test
{
    /**
     *@var \tests\codeception\frontend\UnitTester
     */
    protected $tester;

    protected function _before()
    {
    }

    protected function _after()
    {
    }

    // tests
    public function testMe()
    {
    }
}

其中有一个testMe的公共方法,我们在这个方法里面写一个断言

public function testMe()
{
   $this->assertTrue(2 == 2);
}

运行这个测试,显示ok,测试通过
图片描述
我们再增加一个方法

public function testMe()
    {
       $this->assertTrue(2 == 2);
    }
    public function testM1()
    {
       $this->assertTrue(2 <1);
    }

图片描述
我们再运行一次
这次提示有testm1是fail,testme 是ok
Tests:2 运行了2个测试方法,
assertions:2运行了2次断言(就是执行了2次名字是assert开头的方法)
Failures: 1有1次断言是失败的

查看原文

赞 4 收藏 4 评论 0

wudanyang 赞了回答 · 2019-07-30

解决phpstorm 如何移除无用的use

1.On the main menu, choose Code | Optimize Imports.
2.Press Ctrl+Alt+O.
这里有:https://www.jetbrains.com/hel...

关注 4 回答 3

wudanyang 赞了回答 · 2019-02-21

解决jdk源码在哪看

openjdk源码在线查看网站:Open-source implementation of the Java SE

关注 5 回答 6

wudanyang 关注了标签 · 2018-08-23

rust

一门赋予每个人构建可靠且高效软件能力的语言。

关注 445

wudanyang 收藏了问题 · 2018-06-22

tmux如何实现「窗口名一旦设置,就不再变化」(见图)?

每次打开tmux都会有很多窗口,并且每个窗口都做特定的事情,因此希望每个窗口都有一个特定的可识别名字,但是这个窗口名经常自动变化,不符合我的要求

[尝试的解决方法]
1 查看.tmux.conf中是否有类似automatic,rename的选项被设置,清除它们(仍然没有达成目的) (我的配置:https://github.com/ming2281/_configurations/blob/master/.tmux.conf)
2 Google,但是好像大多是要「能够自动改变窗口名」 (关键词: 「tmux 固定窗口名」 「tmux automatic rename window name」)(无果)

[相关截图]
图片描述

wudanyang 关注了问题 · 2018-06-22

解决tmux如何实现「窗口名一旦设置,就不再变化」(见图)?

每次打开tmux都会有很多窗口,并且每个窗口都做特定的事情,因此希望每个窗口都有一个特定的可识别名字,但是这个窗口名经常自动变化,不符合我的要求

[尝试的解决方法]
1 查看.tmux.conf中是否有类似automatic,rename的选项被设置,清除它们(仍然没有达成目的) (我的配置:https://github.com/ming2281/_configurations/blob/master/.tmux.conf)
2 Google,但是好像大多是要「能够自动改变窗口名」 (关键词: 「tmux 固定窗口名」 「tmux automatic rename window name」)(无果)

[相关截图]
图片描述

关注 4 回答 2

wudanyang 回答了问题 · 2018-02-28

PHP执行shell zip压缩命令

可以写个定时任务

关注 3 回答 2

wudanyang 赞了回答 · 2018-02-23

怎样防止php网页的处理进程在页面关闭后被中途kill掉?

php.ini

ignore_user_abort boolean
默认值为 FALSE 。 如果设置为 TRUE ,在客户端断开连接后,脚本不会被中止。
http://php.net/manual/zh/misc...

function

int ignore_user_abort ([ bool $value ] )
设置客户端断开连接时是否中断脚本的执行

http://www.php.net/manual/zh/...

关注 4 回答 2

认证与成就

  • 获得 25 次点赞
  • 获得 36 枚徽章 获得 0 枚金徽章, 获得 8 枚银徽章, 获得 28 枚铜徽章

擅长技能
编辑

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2015-06-21
个人主页被 750 人浏览