Node.js 的后期诊断和调试 已翻译 100%

TanJx 投递于 2017/06/21 11:46 (共 10 段, 翻译完成于 06-25)
阅读 2217
收藏 71
3
加载中

在你希望判断出你的 Node.js 应用在生产环境中发生了什么错误时,后期诊断和调试就显得尤为重要了。

这里我们探讨 node-report 这个核心项目,用来帮助我们进行后期诊断和调试。

Node.js At Scale 中的全部文章:

使用 npm:

深入 Node.js

使用 Node.js 构建项目

测试 + Node

生产环境中的 Node.js

Node.js 与微服务

  • 请求签名

  • 分布式追踪

  • API 网关

YueZheng
翻译于 2017/06/21 16:56
1

node-report 诊断模块

该模块的目的是生成一个用户可读的诊断摘要文件。 它旨在用于开发和生产环境

产生的报告包括:

  • JavaScript 和原生堆栈跟踪,

  • 堆统计,

  • 系统信息,

  • 资源利用率,

  • 加载的库.

目前,节点报告支持 AIX,Linux,MacOS,SmartOS 和 Windows 上的 Node.js v4,v6 和 v7。

将其添加到你的项目只需要安装 npm 其命令:

npm install node-report --save

//index.js
require('node-report')

将 node-report 添加到应用程序后,它将自动侦听未处理的异常和致命错误事件,并将触发报告生成。也可以通过向 Node.js 进程发送 USR2 信号来触发报告生成。

探花郎啊
翻译于 2017/06/21 18:27
0

node-report 用例

异常诊断

为了简单起见,假设你的应用程序中有以下端点:

function myListener(request, response) {  
  switch (request.url) {
  case '/exception':
    throw new Error('*** exception.js: uncaught exception thrown from function myListener()');
  }
}

一旦调用了 /exception 路由处理程序,这个代码就会抛出一个异常。 为了确保我们获得诊断信息,我们必须将 node-report 模块添加到我们的应用程序中,如前文所示。

require('node-report')  
function my_listener(request, response) {  
  switch (request.url) {
  case '/exception':
    throw new Error('*** exception.js: uncaught exception thrown from function my_listener()');
  }
}

让我们看看端点被调用后会发生什么! 我们的报告刚写进一个文件:

Writing Node.js report to file: node-report.20170506.100759.20988.001.txt  
Node.js report completed

探花郎啊
翻译于 2017/06/21 16:53
0

标头

打开文件后,你会看到如下结果:

=================== Node Report ===================

Event: exception, location: "OnUncaughtException"  
Filename: node-report.20170506.100759.20988.001.txt  
Dump event time:  2017/05/06 10:07:59  
Module load time: 2017/05/06 10:07:53  
Process ID: 20988  
Command line: node demo/exception.js

Node.js version: v6.10.0  
(ares: 1.10.1-DEV, http_parser: 2.7.0, icu: 58.2, modules: 48, openssl: 1.0.2k, 
 uv: 1.9.1, v8: 5.1.281.93, zlib: 1.2.8)

node-report version: 2.1.2 (built against Node.js v6.10.0, 64 bit)

OS version: Darwin 16.4.0 Darwin Kernel Version 16.4.0: Thu Dec 22 22:53:21 PST 2016; root:xnu-3789.41.3~3/RELEASE_X86_64

Machine: Gergelys-MacBook-Pro.local x86_64

你可以将此部分视为诊断摘要的标头 - 它包括..

  • 创建该报告的主要事件

  • Node.js 应用程序是如何被启动的 (node demo/exception.js)

  • 使用了什么版本的 Node.js

  • 主机操作系统

  • 以及 node-report 本身的版本。

堆栈跟踪

报告接下来的一部分包括捕获的堆栈跟踪,包括 JavaScript 和本机部分:

=================== JavaScript Stack Trace ===================
Server.myListener (/Users/gergelyke/Development/risingstack/node-report/demo/exception.js:19:5)  
emitTwo (events.js:106:13)  
Server.emit (events.js:191:7)  
HTTPParser.parserOnIncoming [as onIncoming] (_http_server.js:546:12)  
HTTPParser.parserOnHeadersComplete (_http_common.js:99:23)

在 JavaScript 部分, 你可以看到..

  • 堆栈跟踪 (哪个函数在哪一行被调用),

  • 以及发生异常的地方.

在本机部分,您可以在 Node.js 的本地代码中看到同样的事情 - 只是其在一个较底层的级别

=================== Native Stack Trace ===================
 0: [pc=0x103c0bd50] nodereport::OnUncaughtException(v8::Isolate*) [/Users/gergelyke/Development/risingstack/node-report/api.node]
 1: [pc=0x10057d1c2] v8::internal::Isolate::Throw(v8::internal::Object*, v8::internal::MessageLocation*) [/Users/gergelyke/.nvm/versions/node/v6.10.0/bin/node]
 2: [pc=0x100708691] v8::internal::Runtime_Throw(int, v8::internal::Object**, v8::internal::Isolate*) [/Users/gergelyke/.nvm/versions/node/v6.10.0/bin/node]
 3: [pc=0x3b67f8092a7] 
 4: [pc=0x3b67f99ab41] 
 5: [pc=0x3b67f921533]

探花郎啊
翻译于 2017/06/21 17:07
0

堆和垃圾收集器参数

您可以在堆参数中查看每个堆空间在创建报告过程中是如何执行的:

  • 新空间,

  • 旧空间,

  • 代码空间,

  • 映射空间,

  • 大对象空间.

这些参数包括:

  • 内存大小,

  • 占用内存大小,

  • 容量,

  • 使用空间,

  • 可用空间.

为了更好地了解 Node.js 工作中是如何处理内存的,请参考以下文章:

=================== JavaScript Heap and GC ===================
Heap space name: new_space  
    Memory size: 2,097,152 bytes, committed memory: 2,097,152 bytes
    Capacity: 1,031,680 bytes, used: 530,736 bytes, available: 500,944 bytes
Heap space name: old_space  
    Memory size: 3,100,672 bytes, committed memory: 3,100,672 bytes
    Capacity: 2,494,136 bytes, used: 2,492,728 bytes, available: 1,408 bytes

Total heap memory size: 8,425,472 bytes  
Total heap committed memory: 8,425,472 bytes  
Total used heap memory: 4,283,264 bytes  
Total available heap memory: 1,489,426,608 bytes

Heap memory limit: 1,501,560,832

探花郎啊
翻译于 2017/06/21 17:19
0

资源利用率

资源利用率部分包括这些指标..

  • CPU 使用率,

  • 实际使用物理内存大小,

  • 页面错误信息,

  • 文件系统活跃度.

=================== Resource usage ===================
Process total resource usage:  
  User mode CPU: 0.119704 secs
  Kernel mode CPU: 0.020466 secs
  Average CPU Consumption : 2.33617%
  Maximum resident set size: 21,965,570,048 bytes
  Page faults: 13 (I/O required) 5461 (no I/O required)
  Filesystem activity: 0 reads 3 writes

系统信息

系统信息部分包括..

  • 环境变量,

  • 资源限制 (如打开文件个数, CPU 时间和最大内存空间)

  • 以及加载的库.

探花郎啊
翻译于 2017/06/21 17:27
0

致命错误的诊断

 一旦你的应用程序有致命的错误,node-report 模块也可以为你提供帮助,比如你应用程序运行时内存溢出。

默认情况下,你会收到如下错误信息:

<--- Last few GCs --->

   23249 ms: Mark-sweep 1380.3 (1420.7) -> 1380.3 (1435.7) MB, 695.6 / 0.0 ms [allocation failure] [scavenge might not succeed].
   24227 ms: Mark-sweep 1394.8 (1435.7) -> 1394.8 (1435.7) MB, 953.4 / 0.0 ms (+ 8.3 ms in 231 steps since start of marking, biggest step 1.2 ms) [allocation failure] [scavenge might not succeed].

就其信息本身而言,这些信息没有什么用处。你不知道运行环境,以及应用程序的状态。但随着 node-report 不断上报,这些信息就变的更有价值了。

首先, 在生成的后期诊断总结中,你将获得一个更具描述性的事件:

Event: Allocation failed - JavaScript heap out of memory, location: "MarkCompactCollector: semi-space copy, fallback in old gen"

其次,你将获得本机堆栈跟踪 - 这可以帮助您更好地了解配置失败的原因。

探花郎啊
翻译于 2017/06/21 17:42
0

阻塞操作的诊断

假如你有以下循环,这个循环会阻止到你的事件循环。 这是一场噩梦般表演。

var list = []  
for (let i = 0; i < 10000000000; i++) {  
  for (let j = 0; i < 1000; i++) {
    list.push(new MyRecord())
  }
  for (let j=0; i < 1000; i++) {
    list[j].id += 1
    list[j].account += 2
  }
  for (let j = 0; i < 1000; i++) {
    list.pop()
  }
}

使用 node-report 你可以通过发送 USR2 信号在程序运行期间请求上报, 一旦你这么做,你将获得堆栈跟踪,以及你在 1 分钟内你的应用程序耗费的时间。

( 用于 node-report 资源库的示例)

探花郎啊
翻译于 2017/06/21 17:53
0

node-report 的 API

以编程方式触发报告生成

报告的创建也可以通过使用 JavaScript API 来触发。这样的话,你的报告将保存在文件中,就像它被自动触发一样。

const nodeReport = require('node-report')  
nodeReport.triggerReport()

以字符串形式获取报告

使用 JavaScript API,报告也可以作为字符串检索。

const nodeReport = require('nodereport')  
const report = nodeReport.getReport()

使用非自动触发

如果你不想使用自动触发 (如致命错误或未捕获的异常) 则可以通过调用 API 本身,选择退出自动触发,同样也可以指定其文件名:

const nodeReport = require('node-report/api')
nodeReport.triggerReport('name-of-the-report')

探花郎啊
翻译于 2017/06/21 18:10
0

贡献

如果你希望 Node.js 变得更好,请考虑加入 Postmortem Diagnostics 工作组,在这里你可以为该项目做出贡献。

The Postmortem 工作组致力于支持和改进 Node.js 的后期调试,它旨在提升 Node 的后期调试的作用,以协助开发技术和工具,并且为 Node.js 用户提供已知和可用的技术和工具。

在 Node.js Scale 系列的下一章中,我们将讨论 Node.js 应用程序的性能分析。如果你有任何问题,请在下面的评论中告知我们。

探花郎啊
翻译于 2017/06/21 18:18
0
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
加载中

评论(2)

asdfghjkl12345678
asdfghjkl12345678
英文不好 唉
TanJx
TanJx
确实是有用的文章!Risingstack调查(https://blog.risingstack.com/survey-node-js-developers-struggle-with-debugging-and-downtimes/)显示三分之一的Node开发者在生产系统每周至少一次经验的停机,得费大量时间调试Node应用。
返回顶部
顶部