由一个简单Node服务引申的Node性能分析方法
一、问题现象
一个简单Node服务在500并发的压力下长期运行时会出现内存占用不断增长的问题。
二、分析过程及方法
1.性能压测工具http_load
http_load 是用来测试web服务器吞吐量和负载的测试工具。使用方法示例如下:
|
|
其中,urls.txt是一个文本文件,保存了需要请求的url连接。可包含的参数含义如下:
参数 | 全称 | 含义 |
---|---|---|
-p | -parallel | 并发的用户进程数。 |
-f | -fetches | 总计的访问次数 |
-r | -rate | 含义是每秒的访问频率 |
-s | -seconds | 连续的访问时间 |
本文需要500并发的长时间持续压力,可以运行如下的命令:
|
|
参考资料:通过http_load来测试服务器的性能
2.使用node-inpector进行node程序debug
node-inpector 是用于调试node应用程序的交互界面,类似chrome的开发者面板(Blink Developer Tools)。
使用方法:
(1) 使用npm安装node-inpector
|
|
(2) 以debug模式运行node应用程序,比如我要运行一个node的服务:
|
|
(3) 运行node-inpector
|
|
(4) 使用浏览器打开地址http://127.0.0.1:8080/?port=5858
,界面如下:
3.抓取内存使用堆栈信息
在node-inpector的调试界面,选择Profiles
选项卡,选择第三项Record Heap Allocations
类型。其中,第一项是记录CPU运行信息,展示各个js函数运行的时间;第二项是记录内存堆快照;而第三项会记录一段时间内的内存堆信息。
点击start按钮,并使用http_load开启压力测试。运行一段时间之后,点一左上角的红色圆形按钮(运行结束后变为灰色)。捕获到的快照信息展示如下:
如上图,时间轴中每个时间点的柱状图表示当时申请的内存数量,其中蓝色的部分表示当前使用的内存,灰色的部分表示曾经使用,但后来被释放的内存。时间轴下面是各个对象对内存的占用情况。可以在最下方看到该对象的信息。
可以看到,在时间轴的前部,表示过去时间的部分,还在存在少量蓝色的柱状,这部分就表示长时间没有被回收的内存。如果存在大量内存长期得不到回收,就很有可能发生了内存泄露。
分析方法可参考:Chrome开发者工具之JavaScript内存分析
三、问题原因及解决方式
问题原因:从内存堆栈分析,长期得不到释放的内存是和winston日志输出相关的。尝试关闭所有日志输出,内存果然不再增长。再多次尝试后发现其实是每次请求都要输出一条日志到本地磁盘,但是由于处理请求的并发数过大,磁盘IO来不及处理而堵塞,日志输出队列越堆越多,长期驻留内存。由于如果请求处理速率不变,磁盘IO一直处于来不及处理的状态,队列只能越来越长,内存就会不断增长。
解决方法:禁止每个请求都输出日志。