Node.js 应用故障排查手册 —— Node.js 性能平台使用指南

楔子

前一节中我们借助于 Chrome devtools 实现了对线上 Node.js 应用的 CPU/Memory 问题的排查定位,但是在实际生产实践中,大家会发现 Chrome devtools 更加偏向本地开发模式,因为显然 Chrome devtools 不会负责去生成分析问题所需要的 Dump 文件,这意味着开发者还得额外在线上项目中设置好 v8-profiler 和 heapdump 这样的工具,并且通过额外实现的服务来能够去对线上运行的项目进行实时的状态导出。

加上实际上预备章中除了 CPU/Memory 的问题,我们还会遇到一些需要分析错误日志、磁盘和核心转储文件等才能定位问题的状况,因此在这些场景下,仅仅靠 Chrome devtools 显然会有一些力不从心。正是为了解决广大 Node.js 开发者的这些痛点,我们在这里推荐大家在使用 Node.js 性能平台,即原来的 AliNode,它已经在阿里巴巴集团内部承载了几乎所有的 Node.js 应用线上运行监控和问题排查,因此大家可以放心在生产环境部署使用。

本节将从 Node.js 性能平台 的设计架构、核心能力以及最佳实践等角度,帮助开发者更好地使用这一工具来解决前面提到的异常指标分析和线上 Node.js 应用故障定位。

本书首发在 Github,仓库地址:https://github.com/aliyun-node/Node.js-Troubleshooting-Guide,云栖社区会同步更新。

架构

Node.js 性能平台其实简单的说由三部分组成:云控制台 + AliNode runtime + Agenthub,如下图所示:


具体的部署步骤可以查看官方文档:自助式部署 Runtime。借助于 Node.js 性能平台的整套解决方案,我们可以很方便地实现预备章节中提到的绝大部分异常指标的告警分析的能力。在生产实践过程中,实际上在笔者看来,Node.js 性能平台解决方案其实仅仅是提供了三个最核心却也是最有效的能力:

  • 异常指标告警,即预备节中一些异常指标出现异常时能通过短信/钉钉通知到开发者
  • 导出线上 Node.js 应用状态,包括但不限于即前面 Chrome devtools 一节中提到的 CPU/Memory 状态导出
  • 在线分析结果和更好的 UI 展示,定制化解析应用导出状态和展示,更符合国内开发者习惯

换言之,Node.js 性能平台作为一个产品本身功能也在不断迭代新增修改中,但是以上的三个核心能力一定是第一优先级保障的,其它边边角角的功能则相对来说响应优先级没有那么高。

实际上我们也理解作为使用平台的开发者希望能在一个地方看到 Node.js 线上应用从底层到业务层的所有细节,然而我个人感觉不同的工具都有应该有其核心的能力输出,很多时候不断做加法容易让产品本身定位模糊化以及泛而不精,Node.js 性能平台实际上始终在致力于让原本线上黑盒的运行时状态,能更加直观地反馈给开发者,让 Node.js 应用的开发者面对一些偏向底层的线上疑难杂症能够不再无所适从。

最佳实践

I. 配置合适的告警

线上应用的告警实际上是一种自我发现问题的保护机制,如果没有告警能力,那每次都会等到问题暴露到用户侧导致其反馈才能发现问题,这显然对用户体验非常的不友好。

因此部署完成一个项目后,开发者首先需要去配置合适的告警,而在我们的生产实践中,线上问题通过错误日志、Node.js 进程 CPU/Memory 的分析、核心转储(Core dump)的分析以及磁盘分析能够得出结论,因此我们需要的基本的告警策略也是源自以上五个部分。幸运的是平台已经给我们预设好了这些告警,大家只需要选择一下即可完整这里的告警配置,如下图所示:

在 Node.js 性能平台 的告警页面上有 快速添加规则,点开选中后会自动生成告警规则的阈值表达式模板和报警说明模板,我们可以按照项目实际监控需求进行修改,比如想要对 Node.js 进程的堆内存进行监控,可以选中 Memory 预警 选项,如下图所示:

此时点击 添加报警项 即完整了对进程堆内存的告警,并且将出现告警时需要点击 通知设置->添加到联系人列表 来添加的联系人加入此条规则,如下图所示:

那么在例子中的这条默认的规则里,当我们的 Node.js 进程分配的堆内存超过堆上线的 80%(默认 64 位机器上堆上限是 1.4G)时会触发短信通知到配置绑定到此条规则的联系人。

实际上快速添加规则列表中给大家提供的是最常见的一些预配置好的告警策略,如果这些尚不能满足你的需求,更多定制化的自定义的服务告警策略配置方法可以看官方文档 报警设置。并且除了短信告警,也支持钉钉机器人推送告警消息到群,方便群发感知线上 Node.js 应用态势。

II. 按照告警类型进行分析

按照 I 节中配置完成合适的告警规则后,那么当收到告警短信时就可以按照策略类型进行对应的分析了。本节将按照预备节中比较常见的五大类问题来逐一讲解。

a. 磁盘监控

这个是比较好处理的问题,在快速添加的规则里实际上我们会在服务器的磁盘使用超过 85% 时进行告警,那么收到磁盘告警后,可以连接到服务器,使用如下命令查看那个目录占用比较高:

sudo du -h --max-depth=1 /

找到占比比较高的目录和文件后,看看是否需要备份后删除来释放出磁盘空间。

b. 错误日志

收到特定的错误日志告警后,只需要去对应的项目的 Node.js 性能平台 控制台找到问题 实例 去查看其 异常日志 即可,如下图所示:

这里会按照错误类型进行规整,大家可以结合展示的错误栈信息来进行对应的问题定位。注意这里的错误日志文件需要你在部署 Agenthub 的时候写入配置文件,详细可以参见文档 配置和启动 Agenthub 一节中的 详细配置 内容。

c. 进程 CPU 高

终于到了前一节中借助 v8-profiler 导出 CPU Profile 文件再使用 Chrome devtools 进行分析的异常类型了。那么在 Node.js 性能平台 的整套解决方案下,我们并不需要额外的去依赖类似 v8-profiler 这样的第三方库来实现进程状态的导出,与此相对的,当我们收到 Node.js 应用进程的 CPU 超过我们设置的阈值告警时,我们只需要在控制台对应的 实例 点击 CPU Profile 按钮即可:

默认会给抓取的进程生成 3 分钟的 CPU Profile 文件,等到结束后生成的文件会显示在 文件 页面:

此时点击 转储 即可上传到云端以供在线分析展示了,如下图所示:

这里可以看到有两个 分析 按钮,其实第二个下标带有 (devtools) 的分析按钮实际上就是前一节中提到的 Chrome devtools 分析,这里不再重复讲解了,如果有遗忘的同学可以再去回顾下本大章前一节的内容。我们重点看下第一个 AliNode 定制的分析,点击第一个分析按钮后,可以在新页面看到如下所示内容:

这里其实也是火焰图,但与 Chrome devtools 提供的火焰图不一样的地方在于,这里是将抓取的 3 分钟内的 JS 函数执行进行了聚合展示出来的火焰图,在一些存在多次执行同一个函数(可能每次执行非常短)的情况下,聚合后的火焰图可以很方便的帮助我们找到代码的执行瓶颈来进行对应的优化。

值得一提的是,如果你使用的 AliNode runtime 版本在 v3.11.4 或者 v4.2.1 以上(包含这两个版本)的话,当你的应用出现类死循环问题,比如由于异常的用户参数导致的正则回溯(即执行完这个正则要十几年,类似于 Node.js 进程发生了死循环)这类问题时,可以通过抓取 CPU Profile 文件来很方便地定位到问题代码,详细信息有兴趣的同学可以看下 Node.js 性能平台支持死循环和正则攻击定位。

d. 内存泄漏

与 CPU 高的问题一样,当我们收到 Node.js 应用进程的堆内存占据堆上限的比率超过我们设置的阈值时,我们也不需要类似 heapdump 这样的第三方模块来导出堆快照进行分析,我们还是在控制台对应的 实例 点击 堆快照 按钮即可生成对应 Node.js 进程的堆快照:

生成的堆快照文件同样会显示在 文件 列表页面,点击 转储 将堆快照上传至云端以供接下来的分析:

与上面一样,下标带有 (devtools) 的分析按钮还是前一节中提到的 Chrome devtools 分析,这里还是着重解析下 AliNode 定制的第一个分析按钮,点击后新页面如下图所示:

首先解释下上面的总览栏目的内容信息:

  • 文件大小: 堆快照文件本身的大小
  • Shallow Szie 总大小: 回顾下上一节中的内容,GC 根的 Retained Size 大小其实就是堆大小,也等于堆上分配的所有对象的 Shallow Size 总大小,因此这里其实就是已使用的堆空间
  • 对象个数: 当前堆上分配的 Heap Object 总个数
  • 对象边个数: 这个稍微抽象一些,假如 Object A.b 指向另一个 Object B,我们则认为表示指向关系的 b 属性就是一条边
  • GC Roots 个数: V8 引擎实现的堆分配,其实并不是我们之前为了帮助大家理解简化的只有一个 GC 根的情况,在实际的运行模型下,堆空间内存在许多的 GC 根,这里是真实的 GC 根的个数

这部分的信息旨在给大家一个概览,部分信息需要深入解读堆快照才能彻底理解,如果你实在无法理解其中的几个概览指标信息,其实也无伤大雅,因为这并不影响我们定位问题代码。

简单了解了概览信息的含义后,接着我们来看对于定位 Node.js 应用代码段非常重要的信息,第一个是默认展示的 可疑点 信息,上图中的内容表示 @15249 这个对象占据了堆空间 97.41% 的内存,那么它很可能就是一个泄漏对象,这里又存在两种可能:

  • 此对象本身应该被释放但是却没有释放,造成堆空间占用如此大
  • 此对象的某些属性应该被释放但是却没有释放,造成表象是此对象占据大量的堆空间

要判断是哪一种情况,以及追踪到对应的代码段,我们需要点击图中的 簇视图 链接进行进一步观察:

这里继续解释下什么是簇视图,簇视图实际上是支配树的一个别名,也就是这个视图下我们看到的正是前面一节中提到的从可疑泄漏对象出发的支配树视图,它的好处是,在这个视图下,父节点的 Retained Size 可以直接由其子节点的 Retained Size 累加后再加上父节点自身的 Shallow Size 得到,换言之,在这个视图下我们层层展开即可以看到可疑泄漏对象的内存究竟被哪些子节点占用了。

并且结合前一节的支配树描述,我们可以知道支配树下的父子节点关系,并不一定是真正的堆上空间内的对象父子关系,但是对于那些支配树下父子关系在真正的堆空间内也存在父子节点关系的簇节点,我们将真正的  也用浅紫色标识出来,这部分的  信息对于我们映射到真正的代码段非常有帮助。在这个简单的例子中,我们可以很清晰的看到可疑泄漏对象 @15249 实际上是下属的 test-alinode.js 中存在一个 array 变量,其中存储了四个 45.78 兆的数组导致的问题,这样就找到了问题代码可以进行后续优化。

而在实际生产环境的堆快照分析下,很多情况下簇视图下的父子关系在真实的堆空间中并不存在,那么就不会有这些紫色的边信息展示,这时候我们想要知道可疑泄漏对象如何通过 JavaScript 生成的对象间引用关系引用到后面真正占据掉堆空间的对象(比如上图中的 40 多兆的 Array 对象),我们可以点击 可疑节点自身的地址链接 :

这样就进入到以此对象为起点的堆空间内真正的对象引用关系视图 Search 视图

这个视图因为反映的是堆空间内各个 Heap Object 之间真正的引用连接关系,因此父对象的 Retained Size 并不能直接由子节点的 Retained Size 累加获取,如上图红框内的内容,显然这里的三个子节点 Retained Size 累加已经超过 100%,这也是 Search 视图和簇视图很大的不同点。借助于 Search 视图,我们可以根据其内反映出来的对象和边之间的关系来定位可疑泄漏对象具体是在我们的 JavaScript 代码中的哪一部分生成。

其实看到这边,一些读者应该意识到了这里的 Search 视图实际上对应的就是前一节中提到的 Chrome devtools 的 Containment 视图,只不过这里的起始点是我们选中的对象本身罢了。

最后就是需要提一下 Retainers 视图,它和前一节中提到的 Chrome devtools 中解析堆快照展示结果里面的 Retainers 含义是一致的,它表示对象的父引用关系链,我们可以来看下:

这里 globa@1279 对象的 clearImmediate 属性指向 timers.js()@15325,而 timers.js()@15325 的 context 属性指向了可疑的泄漏对象 system / Context@15249。

在绝大部分的情况下,通过结合 Search 视图 和 Retainers 视图 我们可以定位到指定对象在 JavaScript 代码中的生成位置,而 簇视图 下我们又可以比较方便的知道堆空间被哪些对象占据掉了,那么综合这两部分的信息,我们就可以实现对线上内存泄漏的问题进行分析和代码定位了。

e. 出现核心转储

最后就是收到服务器生成核心转储文件(Core dump 文件)的告警了,这表示我们的进程已经出现了预期之外的 Crash,如果你的 Agenthub 配置正常的话,在 文件 -> Coredump 文件 页面会自动将生成的核心转储文件信息展示出来:

和之前的步骤类似,我们想要看到服务端分析和结果展示,首先需要将服务器上生成的核心转储文件转储到云端,但是与之前的 CPU Profile 和堆快照的转储不一样的地方在于,核心转储文件的分析需要我们提供对应 Node.js 进程的启动执行文件,即 AliNode runtime 文件,这里简化处理为只需要设置 Runtime 版本即可:

点击 设置 runtime 版本 即可进行设置,格式为 alinode-v{x}.{y}.{z} 的形式,比如 alinode-v3.11.5,版本会进行校验,请务必填写你的应用真实在使用的 AliNode runtime 版本。版本填写完成后,我们就可以点击 转储 按钮进行文件转储到云端的操作了:

显然对于核心转储文件来说,Chrome devtools 是没有提供解析功能的,所以这里只有一个 AliNode 定制的分析按钮,点击这个 分析 按钮,即可以看到结果:

这里第一栏的概览信息看文字描述就能理解其含义,所以这里就不再多做解释了,我们来看下比较重要的默认视图 BackTrace 信息视图,此视图下展示的实际上是 Node.js 应用在 Crash 时刻的线程信息,许多开发者认为 Node.js 是单线程的运行模型,其实这句话也不是完全错误,更准确的说法是 单主 JavaScript 工作线程,因为实际上 Node.js 还会开启一些后台线程来处理诸如 GC 里的部分任务。

绝大部分的情况下,应用的 Crash 都是由 JavaScript 工作线程引发的,因此我们需要关注的也仅仅是这个线程,这里显然 BackTrace 信息视图中将 JavaScript 工作线程做了标红和置顶处理,展开后可以看到 Node.js 应用 Crash 那一刻的错误堆栈信息:

因为就算在 JavaScript 的工作线程中,也会存在 Native C/C++ 代码的穿透,但是在问题排查中我们往往只需要去看同样标红的 JavaScript 栈信息即可,像在这个简单的例子中,显然 Crash 是因为视图去启动一个不存在的 JS 文件导致的。

值得一提的是,核心转储文件的分析功能非常的强大,因为在预备节中我们提到其生成的途径除了 Node.js 应用 Crash 的时候由系统内核控制输出外,还可以由 gcore 这样的命令手动强制输出,而本小节我们又看到核心转储文件的分析实际上可以看到此刻的 JavaScript 栈信息以及其入参,结合这两点,我们可以在线上出现 CPU Profile 一节中提到的类死循环问题时直接采用 gcore 生成核心转储文件,然后上传至平台云端进行分析,这样不仅可以看到我们的 Node.js 应用是阻塞在哪一行的 JavaScript 代码,甚至引发阻塞的参数我们也能完整获取到,这对本地复现定位问题的帮助无疑是无比巨大的。

结尾

本节其实给大家介绍了 Node.js 性能平台 的整套面向 Node.js 应用开发的监控、告警、分析和定位问题的解决方案的架构和最佳实践,希望能让大家对平台的能力和如何更好地结合自身项目进行使用有一个整体的理解。

限于篇幅,最佳实践中的 CPU Profile、堆快照和核心转储文件的分析例子都非常的简单,这部分的内容也更多的是旨在帮助大家理解平台提供的工具如何使用以及其分析结果展示的指标含义,那么本书的第三节中,我们会通过一些实际的生产遇到的案例问题借助于 Node.js 性能平台 提供的上述工具分析过程,来帮助大家更好的理解这部分信息,也希望大家在读完这些内容后能有所收获,能对 Node.js 应用在生产中的使用更有信心。


原文链接
本文为云栖社区原创内容,未经允许不得转载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/519304.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

懂编译真的可以为所欲为|不同前端框架下的代码转换

背景 整个前端领域在这几年迅速发展,前端框架也在不断变化,各团队选择的解决方案都不太一致,此外像小程序这种跨端场景和以往的研发方式也不太一样。在日常开发中往往会因为投放平台的不一样需要进行重新编码。前段时间我们需要在淘宝页面上…

面试稳了!网易资深工程师揭秘运维面经!

作者 | 阿文责编 | 伍杏玲出品 | 程序人生(ID:coder_life)受新型冠状病毒影响,很多企业都推迟了复工时间或集体开始远程办公,而一些企业本来计划春节过后开始春季招聘,但是受疫情影响已做出了调整&#xff…

java.lang.NumberFormatException: null

public static void main(String[] args) {String str null;try {int a Integer.parseInt(str);} catch (NumberFormatException e) {e.printStackTrace();}}

Pick!闲鱼亿级商品库中的秒级实时选品

一、业务背景 在电商运营工作中,营销活动是非常重要的部分,对用户增长和GMV都有很大帮助。对电商运营来说,如何从庞大的商品库中筛选出卖家优质商品并推送给有需要的买家购买是每时每刻都要思索的问题,而且这个过程需要尽可能快和…

一文看懂Microsoft Azure的十年变迁

来源 | forbes编译 | 火火酱责编 | Carol出品 | CSDN云计算(ID:CSDNcloud)当微软前首席软件架构师雷奥兹(Ray Ozzie)在2008年的PDC大会上发布Windows Azure时,没人能预估这个软件平台将会为该公司和整个行业…

74HC595

脚位图及说明 管脚说明: 14脚:DS(SER),串行数据输入引脚 13脚:OE,输出使能控制脚,它是低电才使能输出,所以接GND 12脚:RCK(STCP)&…

UI2Code智能生成Flutter代码——机器生成代码

背景 在《UI2CODE--整体设计》篇中,我们提到UI2Code工程的整体流程。前步图片分析之后,我们可以得到对应的DSL布局描述。利用DSL的资讯,结合IntelliJ Plugin介面工具,面向使用者提供生成对应Flutter代码。 本篇主要介绍我们如何…

初始化java工具失败,“初始化 Java 工具”期间发生了内部错误, java.lang.NullPointerException...

今天刚打开eclipse就报了这个错误,我怀疑是昨晚想关电脑的时候,关闭eclipse太快,没有等待工作空间保存就关了电脑的缘故错误如图:(图片来自下方链接博客,因为忘记截图了) 我百度后按照提示,删除了eclipse工…

Node.js 应用故障排查手册 —— 正确打开 Chrome devtools

楔子 前面的预备章节中我们大致了解了如何在服务器上的 Node.js 应用出现问题时,从常规的错误日志、系统/进程指标以及兜底的核心转储这些角度来排查问题。这样就引出了下一个问题:我们知道进程的 CPU/Memory 高,或者拿到了进程 Crash 后的核…

钉钉流量暴增百倍,阿里云抗住了!

2月12日,钉钉已连续在苹果应用商店霸榜7天。记者采访获悉,春节以来,在家办公及在家上课的强需求,使得钉钉后台系统峰值流量暴增百倍。钉钉通过阿里云连续扩容10万台云服务器,成功抗住这一巨大的流量冲击! 2…

PB 级数据处理挑战,Kubernetes如何助力基因分析?

引言 James Watson 和 Francis Crick 于 1953 年发现了 DNA 的双螺旋结构,从此揭开了物种进化和遗传的神秘面纱,开启了人类对数字化遗传的认知,但是人类基因奥秘却是一点点被读懂的。 1956 年,一则癌症和染色体相关性的发现令整…

Nginx 外的另一选择,轻量级开源 Web 服务器 Tengine 发布新版本

新版发布 近日,轻量级开源 Web 服务器 Tengine 发布了2.3.0版本,新增如下特性: ngx_http_proxy_connect_module [1] ,该模块让 Tengine 可以用于正向代理场景,支持对 CONNECT 方法请求的处理;HTTP2 Serve…

腾讯云数据库Redis助力百万企业远程办公

受疫情影响,多数企业员工目前无法回到写字楼办公,学生推迟开学,稳定高效的远程办公和直播授课成为2020年的开年刚需。腾讯从1月24日开始向全国免费开放可支持300人同时在线会议的“腾讯会议”,直至疫情结束。央视新闻联播对此也给…

打通前后端逻辑,客户端Flutter代码一天上线

一、前沿 ​ 随着闲鱼的业务快速增长,运营类的需求也越来越多,其中不乏有很多界面修改或运营坑位的需求。闲鱼的版本现在是每2周一个版本,如何快速迭代产品,跳过窗口期来满足这些需求?另外,闲鱼客户端的包…

迈向电商认知智能时代的基石:阿里电商认知图谱揭秘

阿里妹导读:电商平台最大的挑战是从日益增长的海量商品(数十亿)中挑选出的一个小的子集(几十或上百)展示给用户,以满足用户的个性化的购物需求。为了解决仍存在的重复推荐、缺少新意等问题,我们…

我是如何用6个月,从0编程经验变成数据科学家的?

来源 | medium编译 | 武明利责编 | Carol出品 | CSDN云计算(ID:CSDNcloud)我叫Kate,刚从长达 8 年的学习和艰苦的工作中走出来,没有任何预兆。你可能想问,为什么有人会这么做?不得不说&#xff…

Node.js 应用故障排查手册 —— 综合性 GC 问题和优化

楔子 本章前面两节生产案例分别侧重于单一的 CPU 高和单一的内存问题,我们也给大家详细展示了问题的定位排查过程,那么实际上还有一类相对更复杂的场景——它本质上是 V8 引擎的 GC 引发的问题。 简单的给大家介绍下什么是 GC,GC 实际上是语…

“龙井”开箱评测 |Alibaba Dragonwell 新手上路指南

阿里巴巴有着最丰富的 Java 应用场景,覆盖电商,金融,物流等众多领域,是世界上最大的 Java 用户之一。 2019 年 3 月 21 日,阿里巴巴在北京阿里云峰会上正式宣布开源了 Alibaba Dragonwell 8 产品,并建立了 …

基于角色的访问控制(RBAC)

来源 | 编程新说责编 | Carol出品 | CSDN云计算(ID:CSDNcloud)很多时候,需要对一些事物进行控制,如一个房间,为了不让人随便进,通常会装一把锁,如果要想进入,你必须得有一…

win10 ie中没有java,win10没有ie浏览器怎么处理_window10找不到ie浏览器如何解决

很多用户升级到win10系统之后,发现默认浏览器是edge,想要使用ie浏览器的时候却发现没有ie浏览器,遇到window10找不到ie浏览器的话该怎么办呢,下面随小编一起来看看详细的解决步骤吧。方案一:1、直接搜索,右…