# 常见的 Node.js 部署问题

Node.js 应用程序部署中出现的问题可能有一系列症状,但通常可以分为以下几类

  • JavaScript 代码中未捕获的异常或错误事件
  • 内存使用过多,可能导致内存不足错误
  • 应用程序无响应,可能循环或挂起
  • 表现不佳
  • 在本机代码中崩溃或中止
  • 意外的应用程序行为或功能问题

您用来诊断问题的方法取决于场景,但也可能取决于应用程序部署的要求。生产部署的首要任务是保持应用程序的可用性,这通常涉及故障转移到单独的应用程序实例并立即修复出现故障的应用程序。

开发过程中使用的技术,例如附加调试器或向应用程序添加工具,通常在生产部署中不可用。使用非侵入性且对正在运行的应用程序影响最小的跟踪或监视工具可能是可能的,但在故障点捕获诊断信息(例如日志和转储)通常是最实用的方法。

下面我们将介绍常见的故障场景,并讨论可用于在开发和部署过程中发现问题的工具。

# JavaScript 代码中未捕获的异常或错误事件

JavaScript 代码中未捕获的异常或错误事件通常会导致 Node.js 应用程序终止,并将错误消息和堆栈跟踪写入控制台(stderr 流)。例如,如果使用 Node.js 文件系统 API 的 Node.js 应用程序尝试打开不存在的文件,则会写入以下输出:

// Node.js example application #1 - uncaught exception
const fs = require('fs');

function FileOpen() {
    fs.openSync('/a/non/existent/file', 'r');
}

console.log('example1.js: Node.js application running');
FileOpen();




Error: ENOENT: no such file or directory, open '/non/existent/file'
    at Object.fs.openSync (fs.js:652:18)
    at FileOpen (/home/rnchamberlain/test/exception.js:6:8)
    at Object.<anonymous> (/home/rnchamberlain/test/exception.js:11:1)
    at Module._compile (module.js:573:30)
    at Object.Module._extensions..js (module.js:584:10)
    at Module.load (module.js:507:32)
    at tryModuleLoad (module.js:470:12)
    at Function.Module._load (module.js:462:3)
    at Function.Module.runMain (module.js:609:10)
    at startup (bootstrap_node.js:158:16)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

来自应用程序的 stderr 输出流的异常堆栈跟踪可能足以定位和诊断问题。如果需要更多信息,可以使用多个模块在发生异常时捕获附加信息:

# 针对 JavaScript 中未捕获的错误或异常的工具建议

  • node-report native module: node-report native module 在发生异常时捕获 JavaScript 和本机堆栈跟踪、堆统计信息、平台信息和资源使用数据。
npm install node-report

node -r node-report <application>
1
2
3

# 内存占用过多,可能导致内存不足错误

Node 应用程序过多的内存使用通常由使用操作系统工具(例如,ps或top命令)的脚本或生产监控工具检测到。有时,应用程序会在达到 Node.js 或操作系统中配置的限制时失败。这称为内存不足错误。

内存不足错误会导致 Node.js 应用程序产生错误输出,然后终止应用程序。

来自内存监控工具或错误输出的信息通常不足以让您诊断问题。它不提供应用程序内部通常复杂的内存使用的详细信息。您必须采取额外的步骤来捕获更多信息并使用适当的工具对其进行分析。

# 过度内存使用的工具建议

  • heapdump npm module:使用heapdump (opens new window) 模块捕获堆转储。这是一个 JSON 格式的文件,其中包含应用程序中 JavaScript 对象的类型、大小和数量的详细信息。您可以使用 Google Chrome 浏览器中的开发工具分析堆转储。有关更多信息,请阅读操作方法:堆快照和处理 Node.js 内存泄漏 (opens new window)
  • 带有 llnode v8 插件的 LLDB 调试器:使用带有 llnode v8 插件的 LLDB 调试器。使用操作系统命令(例如gcore(在 Linux 系统上))捕获核心转储。带有 llnode v8 插件的 LLDB 调试器可用于获取应用程序状态的 JavaScript 和本机 C/C++ 堆栈跟踪。

# 3. 应用程序无响应,可能循环或挂起

如果您在生产环境中或应用程序用户自己使用看门狗设施,则可以检测到无响应的 Node.js 应用程序。

您最初可以使用操作系统命令(例如ps(在 Linux 系统上))来确定应用程序是在循环(由高 CPU 使用率表示)还是在等待(由低 CPU 使用率表示)。

# 针对无响应的 Node 应用程序的工具建议

  • 带有信号触发的 node-report npm 模块:使用带有信号触发的 node-report npm 模块来获取一份报告,该报告提供应用程序状态的 JavaScript 和本机 C/C++ 堆栈跟踪。学习更多 (opens new window)
  • Node Application Metrics npm 模块:使用Node Application Metrics (opens new window) npm 模块和Health Center (opens new window)来监控应用程序。
  • 带有 llnode v8 插件的 LLDB 调试器:使用带有 llnode v8 插件的 LLDB 调试器。使用操作系统命令(例如gcore(在 Linux 系统上))捕获核心转储。带有 llnode v8 插件的 LLDB 调试器可用于获取应用程序状态的 JavaScript 和本机 C/C++ 堆栈跟踪。

# 4. 性能不佳

与无响应的 Node.js 应用程序一样,性能问题由生产环境中的看门狗设施或应用程序用户自己检测到。应用程序可能存在响应时间问题或过度使用 CPU 或内存。

# 5. 本机代码崩溃或中止

如果 Node.js 应用程序在本机代码中崩溃或中止,则症状很小。应用程序立即停止,但通常至少会在stdoutorstderr流上生成一条简单的消息。关键的诊断技术是捕获核心转储。ulimit写入核心转储可能需要操作系统配置设置,例如(在 Linux 系统上)

  • 使用带有 llnode v8 插件的 LLDB 调试器:如果可以捕获核心转储,带有 llnode v8 插件的 LLDB 调试器可用于获取显示故障点的本机堆栈跟踪,并允许其他数据,例如寄存器和内存要获得的值。

# 6. 意外的应用程序行为或功能问题

对于意外的应用程序行为或功能问题,症状取决于应用程序,但通常会导致不正确的输出,在例行测试期间或应用程序用户稍后观察到。

# 针对意外应用程序行为的工具建议

  • 内置的Node.js:使用内置的Node.js --trace*,--log和--print选项来获得有关应用程序的更多信息。
  • 带有 llnode v8 插件的 LLDB 调试器:使用带有 llnode v8 插件的 LLDB 调试器。使用操作系统命令(例如gcore(在 Linux 系统上))捕获核心转储。您可以使用带有 llnode v8 插件的 LLDB 调试器来调查应用程序内部的数据(Javascript 对象属性)并检查 JavaScript 应用程序代码。