快速定位NodeJs线上问题 - 之火焰图篇
0x01 背景
前段时间,公司监控群内报警,某个nodeJs项目 CPU 被打满,运维大哥快速重启解决,由于现场没有保留没定位到具体问题。2周后同样的报警又出来了,只能再次祭出重启大法,按照预期果然好了。但是这问题得解啊,总不能让运维老哥哥们写个脚本每两周就重启一次吧。
在定位问题时,发现了有个叫火焰图的工具可以帮助快速准确的定位问题,简直神器,不至于猜来猜去。但是在查找相关资料的时候,发现google到的信息基本都是6、7年前的文章。难道火焰图已经过时了吗,现在已经有更好的方式来定位问题了吗?带着这些疑问决定从根源了解下火焰图的由来。
0x02 火焰图在nodeJs中的发展历程
火焰图本身并不复杂。但是结合 Node.js 的发展历程,每个阶段生成火焰图的形式都有所不同,把我能搜集到的方式列出来,可以根据自己的实际情况进行选择。
1、 Brendan Gregg 大神发明了火焰图,并在 2011年12月正式对外发布。
2、 David Pacheco 紧接着在 2012年1月 用DTrace来抓取node项目的profile并使用火焰图来分析性能。 你的Node项目最耗时地方在哪里?(where-does-your-node-program-spend-its-time)
同期 David Pacheco 又在npm上发布了一个可以统计火焰图的package,有兴趣可以看下他的源码实现,代码不多。stackvis - npm
3、2013年的时候,Google发布了 Google Chrome’s performance analysis tool,就是我们常用的chrome浏览器中的profile收集工具。
4、2013年12月, V8添加了对 perf_events
的支持,允许使用 --perf-basic-prof
参数。支持版本为v0.11.13。使用方法如下:
# *~/node-v0.11.13-linux-x64/bin/node --perf-basic-prof hello.js &*
[1] 31441
# *ls -l /tmp/perf-31441.map*
-rw-r--r-- 1 root root 81920 Sep 17 20:41 /tmp/perf-31441.map
# *tail /tmp/perf-31441.map*
14cec4db98a0 f Stub:BinaryOpICWithAllocationSiteStub(ADD_CreateAllocationMementos:String*Generic->String)
14cec4db9920 f Stub:BinaryOpICWithAllocationSiteStub(ADD_CreateAllocationMementos:String*String->String)
14cec4db99a0 f Stub:BinaryOpICWithAllocationSiteStub(ADD_CreateAllocationMementos:String*Smi->String)
14cec4db9a20 22c LazyCompile:~nextTick node.js:389
14cec4db9cc0 156 Stub:KeyedLoadElementStub
14cec4db9e80 22 KeyedLoadIC:
14cec4db9f20 22 KeyedLoadIC:
14cec4db9fc0 56 Stub:DoubleToIStub
14cec4dba080 10c Stub:KeyedStoreElementStub
复制代码
5、2016年,Node 决定将 Chrome 浏览器的"开发者工具"作为官方的调试工具,使得 Node 脚本也可以使用图形界面调试,这大大方便了开发者。可以参考这篇文章。
$ node --inspect app.js$ node --inspect-brk=9229 app.js
复制代码
这个方法截止目前为止应该是比较方便的抓取方式,本文后面对该方法会有一个详细的介绍。
6、 2016年,ebay 发表了一篇文章,介绍了他们使用 v8-profiler
生成 Node.js 火焰图的过程 : 点燃 Node.js 的火焰 - ebay
目前
v8-profiler
作者应该已经弃坑,可以使用 hyj1991 的v8-profiler-next
,支持 Node v4.x ~ v10.x版本。
7、2017年底,阿里云发布了alinode这个性能分析利器,我们有幸成为第一批使用者,为之后的几次重大活动提功力强有力的保障。
使用alinode可以很方便的一键抓取线上
cpu profile
并进行性能分析。
8、 2018年8月,诞生了一个好用的火焰图分析工具 SpeedScope ,支持3种分析模式,下面有对这个工具详细介绍。
0x03 火焰图的含义
上面已经大致了解了nodeJs里面火焰图的历史。下面来说说如何看懂一张火焰图吧,下图是我们真实项目中的一次压测时抓取的数据。
火焰图基本含义:(来源:如何读懂火焰图? - 阮一峰的网络日志)
- 每一个小块代表了一个函数在栈中的位置(即一个栈帧)。
- y 轴表示调用栈,每一层都是一个函数。调用栈越深,火焰就越高,顶部就是正在执行的函数,下方都是它的父函数。
- x 轴表示抽样数,如果一个函数在 x 轴占据的宽度越宽,就表示它被抽到的次数多,即执行的时间长。注意,x 轴不代表时间,而是所有的调用栈合并后,按字母顺序排列的。
- 小块的宽度代表 CPU 的使用时间,或者说相对于父函数而言使用 CPU 的比例(基于所有样例),越宽则代表占用 CPU 的时间越长,或者使用 CPU 很频繁。如果一个函数在顶层占据的宽度最大,就表示该函数可能存在性能问题。
0x04 案例分析
根据上一环节对火焰图的定义,结合上图的压测数据,已经标注出三个优先级最高,可能存在问题的地方:
- 图中问题1:是Axios中的
request
方法,在顶层占用宽度最大,楼层最高。所以需要优先排查。 - 图中问题2:是Axios中的
transformResponse
方法,后来看了源码,该函数的作用是如果response中为String类型时,会进行JSON.parse()操作。 - 图中问题3:是nunjucks模板引擎渲染页面时,进行序列化的方法。
结合实际情况,下图为该问题发生时大致的效果(因为现场图没有保存下来,下面是后来压测模拟的效果)
- CPU使用率飙升,已经达到100%,服务几乎被压死。但当时qps并不高,只是直接压了有问题的接口。
- TCP链接的
TIME_WAIT
也在持续增长。
根据上面分析,猜测应该是图中问题1的地方所导致的。从代码中定位到确实是我们内部framework中对axios统一封装的 fetch
方法没有处理好导致。问题2、3虽然有优化空间,但不是导致CPU飙升的根源所在。修改后压测数据终于恢复正常。
0x05 最佳实践
上面火焰图历史的部分已经介绍了很多种抓取火焰图的方法,但是很多方法上手难度较高,有的需要侵入代码进行改造。
1、收集
NodeJs v6.3.0+ 推荐使用 --inspect
来抓取,并且使用 chrome-devtools://
来分析。
- 运行node时添加
--inspect
参数
node --inspect app.js
复制代码
- 打开chrome浏览器,直接输入
chrome://inspect
,如下图的地方选择 inspect。
- 点击start后就可以对node项目进行压测了。
- 压测成功后,保存
CPU-xx.cpuprofile
cpuprofile文件到本地。
2、分析
推荐使用 speedscope 来分析火焰图的趋势,打开官网,选择刚才本地保存的文件,支持在线分析也可以安装speedscope到本地。它支持三种模式:
- Time Order 模式:默认按照时间顺序排列;
- Left Heavy 模式:会把最宽的堆栈放在最左侧,依次往右排列,便于快速定位问题;
- Sandwich 模式:可以看到每个函数的相关的时间;
3、验证
优化后,配合 Differential Flame Graphs (红蓝火焰图)分析前后两次profile的趋势变化。
0x06 参考文献
- Flame Graphs
- 如何读懂火焰图? - 阮一峰的网络日志
0x07 推荐文章
- GitHub - aliyun-node/Node.js-Troubleshooting-Guide: Node.js 应用线上/线下故障、压测问题和性能调优指南手册(一期更新结束)
- GitHub - nswbmw/node-in-debugging: 《Node.js 调试指南》
转载于:https://juejin.im/post/5d0346266fb9a07ead59f7a6
快速定位NodeJs线上问题 - 之火焰图篇相关推荐
- 一文带你快速了解 Java 线上问题快速诊断神器 Arthas
文章目录 一.什么是 Arthas 二.特性一览 三.Arthas 能为你做什么? 四.快速安装 1.前提条件 2.一键安装 五.快速使用 1.启动脚本并连接进程 2.启动 jar 包并连接进程 六. ...
- 快速了解 Java 线上问题快速诊断神器 Arthas
快速了解 Java 线上问题快速诊断神器 Arthas 1.什么是 Arthas Arthas 是 Alibaba开源的一款 Java 诊断工具,能够查看 Java 应用的线程状态.JVM 信息等,支 ...
- Nodejs线上日志部署
Nodejs线上日志部署 Nodejs 被越来越多的使用到线上系统中,但线上系统没有日志怎么行呢. 一.forever记录日志 我的线上系统使用forever来启动服务,最开始就直接使用了foreve ...
- java线上问题定位_线上java.lang.OutOfMemoryError问题定位三板斧
OOM(OutOfMemoryError) 问题归根结底三点原因: 本身资源不够 申请的内存太多 资源耗尽 解决思路,换成Java服务分析,三个原因也可以解读为: 有可能是内存分配确实过小,而正常业务 ...
- 一键定位java 线上服务 CPU 100%
传统方法: top oder by with P:1040 // 首先按进程负载排序找到 axLoad(pid) top -Hp 进程PID:1073 // 找到相关负载 线程PID printf & ...
- 线上CPU100%?看看这篇是怎么排查的。
前言 作为后端开发工程师,当收到线上服务器CPU负载过高告警时,你会这么做?重启服务,忽略告警?不过在我看来一个合格的工程师是一定要定位到具体问题所在的,从而 fix 它.下面记录一下线上服务器 CP ...
- 线上CPU100%?看看这篇是怎么排查的!
前言 作为后端开发工程师,当收到线上服务器CPU负载过高告警时,你会这么做?重启服务,忽略告警?不过在我看来一个合格的工程师是一定要定位到具体问题所在的,从而 fix 它.下面记录一下线上服务器 CP ...
- 2021年中国花卉电商产业现状与趋势分析,鲜花需求持续上升,线上趋势推进「图」
一.花卉电商简述 1.分类状况 花卉产品主要包括鲜花.盆栽植物和盆景等.按照用途鲜花可分为礼品花和日常使用,整体需求广泛.而盆栽和盆景主要适用于装饰作用,在办公场所和家庭场景应用较多. 花卉电商产品分 ...
- 从0开始学会搭建一个最简单的属于自己的云线上网站(纯小白篇)
大家好,我本人是一名快大二在读学生,自学过接近七年的计算机IT编程,当初新手的时候也是来过CSDN进行相关的学习,但是学成以后都是在自己钻研很多更深层次的技术并没有想过来到CSDN自己也发表一些文章进 ...
最新文章
- 基于r-Kernel的LiteOS操作系统
- mmap映射大于4g的文件_iOS文件内存映射——MMAP
- deep_sort_face
- fragments lifecycle
- Leetcode 102.二叉树的层序遍历 (每日一题 20210628)
- Fiori Elements的metadata和ui annotation
- 我看ITIL在中国(六):如何建立有中国特色的IT运维管理平台【二】
- VS2017/2019 F12无法导航到定义
- 《大数据》第1期“聚焦”——从系统角度审视大数据计算
- cogs1799 [国家集训队2012]tree(伍一鸣)
- C语言-数据结构-可变长顺序表的查找操作
- 多线程(thread)+进程(Process)
- Reflector.FileDisassembler的一个bug
- iPhone 手机烧号的一些概念:五码烧号 vs OTA烧号
- 解决navicat在未联网的情况下访问不了MySQL数据库的现象
- 两堆草前饿死的驴——选择永远是件痛苦的事
- 用浏览器怎样监控网页内容变化
- 穷查理宝典_穷查理宝典
- OP-TEE中的线程管理(四)
- 最强大脑-星际迷航-JQuery 版本
热门文章
- 2753:走迷宫(dfs+初剪)//可以说是很水了。。。
- 运行mvc项目报错 %@ Application Codebehind=Global.asax.cs Inherits=NHAPPAPI.MvcApplication Language=C...
- HDU - 4456 Crowd
- WCF 4 高级编程 - 读书笔记
- mysql执行脚本的方法
- LocalDate,LocalDate,LocateDateTime的常用方法
- Springboot整合RabbitMQ,包含direct,topic,fanout三种模式的整合
- ijkplayer 视频播放
- html下拉表覆盖透明,css透明元素如何遮挡住fixed元素
- 以太网的分层架构_读《企业应用架构模式》记录-分层