现象:
pm2占用CPU达到100%,但是pm2管理的进程占用的CPU在50%-60%,从而导致pm2分发成为性能瓶颈;
因为nodejs测试代码结构很简单,处理请求的速度过快,从而导致当pm2管理的子进程达到CPU使用率50%-60%的时候,PM2占用的CPU就达到100%了,发送的请求pm2进程就转发不过来了。
服务器说明:
CPU:32核
内存:64G
pm2集群启动实例配置:
[root@elk-sdzx express_example]# cat /opt/shell/process.json
{
apps : [{
name : "express_example",
cwd : "/www/express_example",
script : "./bin/www",
instances : 32,
exec_mode : "cluster",
log_type : "json",
error_file : "/www/pm2_run/log/express_example-err.log",
out_file : "/www/pm2_run/log/express_example-out.log",
combine_logs: true,
max_memory_restart : "512M",
pid_file : "/www/pm2_run/pid/express_example.pid",
env : {
"NODE_ENV": "production",
"PORT": 8080
},
watch : false
}]
}
压测命令:
ab -c 30 -n 500000 http://127.0.0.1:8080/
ab -c 36 -n 500000 http://127.0.0.1:8080/
ab -c 40 -n 500000 http://127.0.0.1:8080/
并发为40的时候pm2的CPU就100%了。
解决办法:
降低单个nodejs进程的请求处理速度,把原来循环100次改成了1000次。
理解分析总结:
其实pm2进程和它管理的业务进程性能是相对的,这里的nodejs代码只是为了测试nodejs性能而写的,没有调用任何其他http接口或者第三方接口及中间件,导致单个nodejs进程处理请求的速度很快,从而容易造成pm2进程变成性能瓶颈。而相反的,如果降低了nodejs进程的请求处理速度,那么相对的,pm2转发请求的速度就会造成nodejs进程跑满CPU,而即使所有的nodejs进程都跑满了CPU,但pm2进程依然没有跑满CPU。
以下为计算示例:
示例1:
假设pm2进程每秒转发10W个请求是上限,这个时候其CPU使用率会达到100%;
每个nodejs进程每秒处理10000个请求是上限,这个时候其CPU使用率达到100%;
场景:
启动32个nodejs进程,也就是说每秒最多处理320000个请求可以把机器的32颗CPU都跑到100%;但是,在这种情况下,pm2会率先占满CPU称为性能瓶颈,从而导致nodejs进程始终跑不满CPU。
计算如下:
当pm2跑满CPU时,转发请求的速度为100000/s;
基于轮询负载均衡算法,算出:每个nodejs进程由pm2分配请求的速度为3125/s。所以每个nodejs占用的CPU为3125/10000=31.25%左右。从而无论怎么增加压测并发和请求数,nodejs的CPU也是压不上去的。
示例2:
假设pm2进程每秒转发10W个请求是上限,这个时候其CPU使用率会达到100%;
每个nodejs进程每秒处理1000个请求是上限,这个时候其CPU使用率达到100%;
场景:
启动32个nodejs进程,也就是说每秒最多处理32000个请求可以把机器的32颗CPU都跑到100%;但是,在这种情况下,nodejs进程所占用的CPU会率先成为性能瓶颈。
计算如下:
当32的nodejs进程都跑满CPU时,处理请求的速度为32000/s;
此时,pm2进程占用的CPU使用率为32000/100000=32%左右,也就是说这个时候nodejs代码成了性能瓶颈。pm2的CPU使用率最大也就32%左右;