故事的起因是这样的:
因有需求对前端传来的文件进行实时处理,要求是实时用厂家的SDK请求处理这些文件,将结果实时写入后端数据库,所以写了实时转发程序A,原理采用了内核的inotify机制,监测上传目录下有文件创建后执行消费处理,nohup A 放在后台实时守护处理,消费程序 M和N 为两个厂家的python SDK,消费处理完后入MySQL数据库。
程序A:
#!/bin/sh
export PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin:/root/bin
/usr/bin/inotifywait -mrq --timefmt ‘%d/%m/%y %H:%M‘ --format ‘%f‘ -e create DIR | while read file
#执行上面命令,是让inotifywait监听DIR目录,当监听到有发生create事件发生时,按%Xe %w%f的格式输出
do
python27 doM.py &
python27 doN.py &
done
但发现当文件量大后,程序A跑满了CPU,所以程序肯定有异常,所以开始寻找原因,因为上传目录都为一个目录,所以原本判断是否是硬件资源不够,IO/内存不够等导致CPU占用过高? 后来top/iostat等判断发现硬件根本没有瓶颈,我的服务器都是高配机,后来觉得是否是因为上传的目录下文件过多,导致内核处理的有延时?毕竟那目录下几万甚至几十W个文件呢,每台服务器每秒可能同时有几百个文件上传写入,所以对目录下文件进行定期删除处理,可是发现删除完之后CPU还是跑的有点高,虽然不跑满,但还是比较高啊,仔细想想A抛出两个进程,是否会是因为进程上下文切换CS过高导致的呢? 用vmstat发现,CS有40000+多,确实很高,所以决定先把B和C代码合并试一下,让A只抛出一个程序请求呢,改为:
#!/bin/sh
export PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin:/root/bin
/usr/bin/inotifywait -mrq --timefmt ‘%d/%m/%y %H:%M‘ --format ‘%f‘ -e create DIR | while read file
#执行上面命令,是让inotifywait监听DIR目录,当监听到有发生create事件发生时,按%Xe %w%f的格式输出
do
python27 allDo.py &
done
此时再vmstat查看cs已经降低至8000了,程序A的cpu使用率降低了几十倍,心里舒坦了,世界安宁了,性能杠杆的
所以对于写多进程多线程时候容易出现此类问题吧。