砥砺奋进谱新篇,且看旧貌换新颜。欢迎访问新的 IBM Developer 中文网站! 了解详情

IBM Developer 博客

通过 IBM Developer 关注最新动态并获取信息

Node.js 14 版本发布了。了解与诊断、性能和国际化相关的新功能和增强功能。


4 月份意味着又要开始发布新的 Node.js 版本了。今天(4 月 21 日),我们将要发布 Node.js 14,其中包含对 Node.js 用户(包括 IBM 客户)非常重要的新功能。虽然到 10 月份才会升级到长期支持 (LTS) 版本,但是我们仍需要客户和更大的生态系统来试用此版本并提供反馈意见。这样,我们就可以提前解决问题,并确保此版本、生态系统和客户在升级时做好全面准备。

14.x 版本提供了一些关键增强功能,包括:增加了“诊断报告”(Diagnostic Report)这项稳定功能、提供了实验性异步本地存储 API(可通过流程中的不同步骤和外部资源来跟踪事务)、支持国际化,以及简化了原生模块的使用。

观看 Node.js 版本经理 Bethany Griggs 与 TSC 主席 Michael Dawson 关于新版本的讨论视频:

IBM 的 Node.js 项目参与战略是专注于我们认为对客户很重要的方面,包括可预测的稳定版本、平台支持、安全性、诊断、性能、代码质量和安全网以及关键功能。14.x 版本在上述多个方面都提供了新功能和增强功能,在以下各节中,我将深入探讨一些关键要点。

增加了“诊断报告”这项稳定功能

从 Node.js 14 开始提供了诊断报告这项稳定功能。此功能将提供一份易于使用的报告,其中包含对生产问题的初始诊断和分类十分有用的信息。 我们发现,此功能对于提供跨语言(包括 Node.js、Java 和 Swift)的客户支持非常重要。“诊断报告”是 Node.js 中内置的一项稳定功能,它不仅可用于生产环境中,还可用于快速解决问题。

要了解更多信息,请查看 Gireesh Punathil(Node.js 合作者兼 IBM 员工)撰写的使用 Diagnostic Report 轻松识别 Node.js 应用程序中的问题

“诊断报告”将提供一份基于 JSON 的报告,机器和人类都可阅读此报告。此类报告会提供有价值的信息,可帮助您快速诊断问题。例如,假设您的应用程序间歇性崩溃,并且没有生成核心文件。您可以生成“诊断报告”,并检查用户限制以确保将其配置为允许生成核心文件。在此示例中,您可以看到已设置了 ulimit,这会导致您无法获得核心文件(limit 设置为 0)。

    "userLimits": {
    "core_file_size_blocks": {
      "soft": 0,
      "hard": "unlimited"
    },

同样,如果应用程序内存不足,那么可以通过 max-old-space-size 命令行参数来检查最大堆大小是否受到限制:

 "commandLine": [
      “node",
      "--max-old-space-size=128",
      "testd

您可以将“诊断报告”配置为在发生某些事件(如接收信号、未捕获的异常或致命错误)时生成。也可以通过几行代码在应用程序中生成“诊断报告”:

const process = require('process');
process.report.writeReport();

如果从命令行运行,那么可能会很容易获得此信息。但是,由于当今的许多生产部署都在容器中进行,而这些容器的管理和配置都不在您的掌控之下,因此“诊断报告”通常可以提供有价值的洞察,以便您了解外部配置对于应用程序运行方式可能造成的影响。

如果尚未使用“诊断报告”,那么建议您仔细阅读其相关信息,以了解如何在生产环境中使用此功能。您可以在以下 API 文档中深入了解此功能:https://nodejs.org/api/report.html

使诊断报告更易于使用

经验表明,通常我们需要依次查看多个诊断报告或者在诊断报告中查找某个可能的问题。report-toolkit 是 IBM 开发的一款工具,用于简化诊断报告的使用。

虽然 Node.js 14 版本中不包含 report-toolkit(因为“诊断报告”现在是一项稳定功能),但我们还是希望借这个机会让大家了解 report-toolkit,试用一下并提供反馈意见。

report-toolkit 整合了一些关键功能:

  • 用于查找常见问题的内置 inspect 规则
  • 编辑密钥
  • 两个或更多个诊断报告在特定用途上的差异
  • 用于提取和格式化关键信息的转换程序

您可以在 IBM 员工 Christopher Hiller 撰写的介绍用于 Node.js 诊断报告的报告工具包(report toolkit) 一文中进一步了解 report-toolkit。您会发现,结合使用“诊断报告”和 report-toolkit,可以简化问题调查过程和信息共享。

实验性异步本地存储 API

对于企业来说,非常有必要通过流程中的不同步骤以及外部资源(例如,数据库调用)来跟踪事务。此功能通常提供了在识别应用程序中出现问题的位置或确定性能瓶颈时需要使用的信息。

Node.js 的异步特性意味着,其他语言的解决方案(例如,线程本地存储)不适用于 Node.js。社区一直在研究 API,通过多个版本上的异步调用来帮助跟踪和管理上下文。已增加了实验性 Async Hooks API,以用于帮助解决此问题,但目前仍在努力提高其稳定性。

Node.js 14 新增了一个名为 AsyncLocalStorage 的实验性 API。希望这个更高级的 API 能够更容易实现稳定,因为它只公开了较少的内部元素,并且提供了一个更简单的 API。虽然许多 npm 模块都提供了类似的功能,但由于难以维护和全方位使用,因此大家一致认为应在 Node.js 中提供 API。我很高兴看到此关键功能变成了核心功能。

我们来看一看这个 API 的实际应用:

const AsyncLocalStorage = require('async_hooks').AsyncLocalStorage;
const asyncLocal1 = new AsyncLocalStorage();

function logData() {
  console.log(asyncLocal1.getStore(['url']));
}

function accept(request, response) {
  asyncLocal1.getStore()['url'] = request.url;
  setTimeout(logData, 100);
};

asyncLocal1.run(new Object(), accept.bind(null, { url: 'url1'}, {}));
setTimeout(() => { asyncLocal1.run(new Object(), accept.bind(null, { url: 'url2'}, {})) },
  500);

此示例试图模拟 Web 服务器场景,该服务器可能同时具有多个活动的异步流(每个连接对应一个异步流)。这个示例并不完整,因为它只提供了说明此 API 工作方式的那几行代码。

首先获取对此 API 的引用,并创建一个 AsyncLocalStorage 实例。您将注意到,异步本地存储 API 是顶级名称空间 async_hooks 的一部分。一个重要方面是,根据 JavaScript 作用域限定规则,所有需要访问异步流上下文的代码都必须能够使用这个对象。

服务器将针对每个连接请求调用 accept 函数。在此示例中,只是设置了 asyncLocal1.getStore() 所返回的存储空间中的一个值,然后使用 SetTimeout 进行异步调用。

调用 logData 函数时,它会通过 accept 函数提取 AsyncLocalStorage 中存储的值,然后将其记录到标准输出中。

最后几行展示了如何使用 asyncLocal1.run() 运行 accept 调用。异步流的存储仅传播到该 run 方法的作用域内的函数。此 API 还提供了一些其他方法,您可以在需要时使用这些方法来停止传播流中的存储。

此时,您提出的第一个问题可能是“使用全局对象(如 let url;)能否执行相同的操作,并从该处改为写入/读取数据?” 如果在给定时间只有一个活动的流,那么这样做是可行的,但问题是,如果您有多个流,那么这些流会覆盖彼此的值。值得注意的关键一点是,即使所有流都使用相同的全局对象 asyncLocal1,但是在异步流中调用 getStore() 时,也会得到该流独有的对象。

例如,在此示例的两个流中:

asyncLocal1.run(new Object(), accept.bind(null, { url: 'url1'}, {}));
  --> asyncLocal1.getStore()
    --> store1
setTimeout(() => { asyncLocal1.run(new Object(), accept.bind(null, { url: 'url2'}, {})) }, 500);
  --> asyncLocal1.getStore()
    --> store2

我希望这能够激发您对该 API 的兴趣,并开始试用该 API。虽然它是使用以前的 npm 包中学到的内容构建的,但是我们仍需要您的帮助,以便确保它涵盖了所有必需用例并且易于使用。

国际化支持

国际化是 IBM 内部员工和 IBM 客户的一个关键需求。虽然国际化不是 Node.js 14 中的新功能,但在 10 月份升级到 LTS 时,Node.js 14 将是第一个默认包含完整 ICU 数据的 LTS 版本。您可以在 Node.js 13 版本博客中进一步了解此功能。

例如,为 weather.com 提供支持的一个大型 Node.js 部署就支持 230 多种语言环境,并且已本地化为大约 60 种语言。进一步了解 Node.js 如何为 weather.com 提供支持。

简化了原生模块

Node.js 14 使得创建、构建和支持原生模块(也称为“插件”)变得更加容易。IBM 是 N-API 的持续贡献者之一,并且 Node 14 附带了 N-API V6,后者包含对 BigInt 的支持并提供一些其他改进。有关 N-API 的更多信息,请查看 API 文档node-addon-api

感谢我们出色的团队

最后,我要感谢发布团队(包括发布经理和 IBM 员工 Bethany Griggs 在内),感谢他们为 Node.js 14 的顺利发布而付出的所有努力。我还想感谢来自编译工作组的大力支持,当然,也要感谢个人贡献者。

如何为 Node.js 做出贡献

提交代码并参与 Node.js 团队工作并不是为 Node.js 的持续成功做出贡献的唯一途径。作为 Node.js 包开发者或最终用户,我号召您提前测试,并经常测试,以便为 Node.js 项目提供帮助和反馈意见。

我们以 6 个月为固定周期(每年的 4 月和 10 月)发布一次主要版本,这样,我们就有充足的时间来提前测试版本,以便在版本升级到 LTS 时不会出现任何意外。我们需要您帮忙进行测试。一旦版本为 LTS,就需要考虑定期在 LTS 版本上测试应用程序和包,以确保要迁移到这些版本的最终用户具有绝佳的体验。如果您发现问题,请在 Node.js 代码库中提交问题来进行报告。

如果您是包维护人员,请考虑将您的版本和支持周期与 Node.js 版本线保持一致。这篇文章由 OpenJS 基金会发表,它充分说明了为什么这样做有益于生态系统。

了解更多信息

如果您要进一步了解此版本,请查看有关 Node.js 14 版本发布的社区博客文章

您还可以:

本文翻译自:Node.js 14 release: New diagnostic tools, features, and performance enhancements(2020-04-21)