诺亚方舟

沉淀

实践统计php-fpm负载情况

最近想对线上机器web负载情况做一次调查,线上环境是nginx+php-fpm的搭配,我们知道一次http请求的流程是

①客户端发起请求到80等端口;

②服务端nginx主进程监控80端口,对任务进行分发给worker进程;

③nginx的worker进程根据配置将请求转发给fcgi,这里环境是9000端口的php-fpm;

④监控9000端口的php-fpm主进程根据配置将请求静态(或动态)交给php-fpm子进程处理;

⑤php-fpm子进程处理完毕原路返回数据报。

于是乎,我们统计fpm负载情况也就有方案了:根据端口监听情况来统计。统计代码也很简单:

 

1
2
3
netstat -anpt | grep 'php' | awk -F ' ' '{print $7}' | awk -F '/' '{print $1}' | sort | uniq | wc -l
//注:我这里把端口监听进程的进程名也打出来,可以看到php>5.3的进程名是php-fpm,php<5.3抓出来的是php-cgi
//这里还有个细节,因为抓的关键字是php,所以对抓出来的进程号进行率重,抓端口监听号会便捷些

下面描述我的实践过程:

一,了解php-fpm配置参数

fpm可支持多进程池,不同进程池的配置可以分别配置,下图为实例。

配置文件

1
2
3
4
5
6
7
8
9
10
listen = 127.0.0.1:9000//fpm监听端口,即nginx中php处理的地址,一般默认值即可。
listen.allowed_clients = 127.0.0.1//允许访问FastCGI进程的IP,设置any为不限制IP,如果要设置其他主机的nginx也能访问这台FPM进程,listen处要设置成本地可被访问的IP。默认值是any。每个地址是用逗号分隔. 如果没有设置或者为空,则允许任何服务器请求连接.
user = www//启动进程的用户
group = www//启动进程的组
<span style="color: #ff0000;"><strong>pm = dynamic</strong></span>//如何控制子进程,选项有static和dynamic。如果选择static,则由pm.max_children指定固定的子进程数;如果选择dynamic,则由下开参数决定。对于专用服务器,pm可以设置为static。
pm.max_children = 5//子进程最大数
pm.start_servers = 3 //启动时的进程数
pm.min_spare_servers = 3 //保证空闲进程数最小值,如果空闲进程小于此值,则创建新的子进程
pm.max_spare_servers = 3 //保证空闲进程数最大值,如果空闲进程大于此值,此进行清理
pm.max_requests = 1000//设置每个子进程重生之前服务的请求数. 对于可能存在内存泄漏的第三方模块来说是非常有用的. 如果设置为 '0′ 则一直接受请求. 等同于 PHP_FCGI_MAX_REQUESTS 环境变量. 默认值: 0.

这里pm的值设置会对php产生比较大的影响,如果设置为static,则php-fpm启动后会生成多个常驻子进程进行等待,若为dynamic则会根据fpm的优化策略来控制子进程数,这两种方案各有好处,如果是专门的web服务可以选用static,这样可以减少开辟进程带来的cpu开销。

dynamic

图1:php=5.4的static方式

static

图2:php=5.2的dynamic方式

注意:这里由于php版本不同,所以看到的进程名是不同的。

二,验证dynamic形式与进程监听状态

了解了fpm的工作机制后,下面我们来验证猜想。采用的方案是利用压测工具http_load和监控工具watch来观察变化。压测前的状态:

压测前端口监听状态

图3:压测前端口监听状态

进程状态如图一。

这里用到的两条命令:

 

1
2
//压测机命令
http_load -rate 10 -seconds 10 url.txt //url.txt为一个url:http://iamjs.net/lbb.php
1
2
3
//监控机命令
 watch -n 0.5 'netstat -anpt | grep php-fpm'
watch -n 1 'ps aux | grep php | grep -v grep'
1
2
3
//接口内容
header("Content-Type:text/html;Charset=utf-8");
sleep(1);

上面例子用的是按每分钟10次的频率进行10s的压测,结果如下图:

压测监听进程结果

图4:压测监听进程结果

压测监听端口结果

图5:压测监听端口结果

由此可以验证我们的猜想。

三,结论

实际上我们可以写个脚本定时监控php进程的端口监听数,如果长期和fpm设置的定值(或最大值)一样,并且nginx经常出现502的错误,就要考虑调高fpm控制的进程数了。

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>