又开始讲故事了,前言部分,喝着茶水看着报纸,然后手机嗡嗡作响,不用想肯定不是美女求助,尼玛坑爹的报警。
看了下原因,由于多个小业务混跑,一个业务由于数据库读写问题导致整个php池被打满。然后所有的小业务都半死。。。 数据库读写的问题暂且不论,毕竟不是专业dba,就环境隔离搞了cgroup+supervistor。期间遇到了些问题,值得有些同学借鉴。
######################################################
cgroup 与 supervistor详细介绍省略。
为啥是这个组合:cgroup做资源隔离。supervistor做服务守护。为啥在一起,因为缘分。。。 因为一个参数的原因,下面会揭晓。
首先安装:
yum install libcgroup bcgroup-tools
yum install supervisor
如果yum源里没有,就配置个epel源 或者 阿里源 参照这个
然后说配置:
cgroup:
/etc/cgconfig.conf
group SIXTY { #组名 cpu { #子系统 有哪些子系统可做隔离 参照命令 # lssubsys cpu.shares = 6000; #cpu配额,单独配置无效,需要与其他组配额一起生效。例如本次配置share有 6000,3000,1000三个档位,分别用于不用的服务池资源。这里6000占用系统cpu的60%,或者理解为60%的cpu计算资源,当其他组占用少时可以更多的占用,竞争出现才有限制效果。 #cpu.cfs_quota_us = 200000; #cpu基于cfs算法的配额时间片,例如周期起100000,时间片为200000那么可以同时占用2个cpu周期。这两个配合使用,可以限制cpu计算资源的绝对值,而share是相对值 #cpu.cfs_period_us = 100000; #单核cpu的时间周期 } memory { memory.soft_limit_in_bytes=10G; #内存软限制 memory.limit_in_bytes=20G; #内存硬限制 memory.swappiness=0; #是否交换 memory.oom_control=0; #到达内存硬限制是否oom kill,0表示kill,1表示等待内存释放,期间其他进程阻塞。在组内的表现为夯住。 这就是上面说的缘分参数,设置了oom kill,又要保证服务只能引入守护。 } } group THIRTY { cpu { cpu.shares = 3000; } memory { memory.soft_limit_in_bytes=5G; memory.limit_in_bytes=10G; memory.swappiness=0; memory.oom_control=0; } } group TEN { cpu { cpu.shares = 1000; } memory { memory.soft_limit_in_bytes=1G; memory.limit_in_bytes=2G; memory.swappiness=0; memory.oom_control=0; } }
supervistor配置:
/etc/supervisord.d/php-fpm.ini
[program:php-fpm] directory=/var/supervisord/ stdout_logfile=/var/supervisord/php-fpm.log command=/etc/init.d/php-fpm start #脚本启动 #command= /usr/local/sbin/php-fpm --fpm-config /etc/php-fpm9000.conf --pid /var/run/php-fpm9000.pid #命令启动 跟脚本启动有区别 autostart=true #随supervistor自动启动 autorestart=true #服务挂了释放重启服务 startsecs=5 #启动成功判断周期 priority=1 #启动优先级 低者优先 user=root #stopasgroup=true killasgroup=true #重启的时是否kill被守护进程的子进程,如果不,这些进程会变成孤儿进程被init接管。例如守护php-fpm,其实只是守护master进程。如果退出不kill 子进程,会出现重启失败的问题。 stdout_logfile_maxbytes=20MB stdout_logfile_backups=20
php-fpm启动命令 或者脚本修改,不能后台deam运行:
php-fpm.conf 中 daemonize = no 必须是no
如果命令启动 不能用 --daemonize supervistor的cmd可以配置为:/usr/local/sbin/php-fpm --fpm-config /etc/php-fpm9000.conf --pid /var/run/php-fpm9000.pid
脚本启动需要修改启动命令为:
cgexec -g memory:GROUP1 -g cpu:GROUP1 exec $php_fpm_BIN $php_opts #exec $php_fpm_BIN $php_opts #$php_fpm_BIN --daemonize $php_opts
注意exec 这个是必须的,最下面的详解中不用exec启动的现象,欢迎尝试,至于为什么请大家看下exec运行命令的特点,欢迎留言区讨论哈。
不能用守护进程启动的原因:
deamonize参数,表示master进程以守护进程启动。根据supervistor的文档:被守护的进程(php-fpm),不能以守护进程(deamon)的形式运行。这是由于守护进程通常在fork子进程后会终结父进程,也就是supervistor创建的父进程退出,此时,supervistor无法再健康已经退出的进程fork的子进程。关于deamon,可以参考Linux Daemon Writing HOWTO。
配置说完,就是启动了:
service cgconfig restart
service cgred restart
service supervisord start
当然 还会涉及php分池的问题,也就是启动多个php-fpm master 监听多个端口,然后就是修改nginx配置, 这应该都不是事。所以我也懒得写啦 理解下哈。
######################################################
然后说下其中遇到的一些问题:
查看status,退出太快了。。:
php-fpm FATAL Exited too quickly (process log may have details)
supervistor重启php-fpm报错 异常终止:
php-fpm:ERROR (abnormal termination)
原因:
exit quickly是由于脚本启动,使用--deamon参数。启动后直接退出导致pid存在。在supervistor的包活周期内检测到退出然后报错。
restart 发现php-fpm未正常退出,也就是上面说的deamon的问题。注意这里master进程的PPID是1 父进程也就是脚本已经退出。
解决办法:
最上面已经说了 不使用--deamon 然后脚本启动要使用exec
supervistor 的killasgroup 参数可以kill被守护进程的子进程,但是子进程的子进程是无能为力的
######################################################
然后是cgroup的一些实验 以及一些其他截图
一个申请内存的简单的程序:
#vim oom.c #include <stdlib.h> #include <stdio.h> #include <string.h> int main(int argc, char **argv) { int max = -1; int mb = 0; char *buffer; int i; #define SIZE 100 unsigned int *p = malloc(1024 * 1024 * SIZE); printf("malloc buffer: %p\n", p); for (i = 0; i < 1024 * 1024 * (SIZE/sizeof(int)); i++) { p[i] = 123; if ((i & 0xFFFFF) == 0) { printf("%dMB written\n", i >> 18); usleep(100000); } } pause(); return 0; }
注意编译下:
gcc oom.c
然后运行就是这样的了:
申请占用100M内存
修改了下程序中size 然后编译 能够申请500M
简单的cgroup隔离了下内存 这里申请内存失败 然后夯住了 也就是上面说到的oom kill是否开启的问题。如果不开启这里不能进行操作。完全夯死。
这是share 2000:1000的对比图
这是php启动脚本中修改后命令:
最后是已经搞定的图,重启是好用的:
####################################################
感谢看到最后,打铁到24:00 我要去补觉 !!!!!!!!!!!
原文地址:http://blog.51cto.com/welcomeweb/2136875