如何优化 Node.js 生产基础设施:最佳实践

前言

在 Forward Email,我们花费了数年时间完善 Node.js 生产环境的搭建。本指南全面分享了我们久经考验的 Node.js 生产部署最佳实践,重点介绍性能优化、监控以及我们在扩展 Node.js 应用程序以处理每日数百万笔交易过程中积累的经验教训。

我们 573% 的单核性能优化革命

当我们从 Intel 处理器迁移到 AMD Ryzen 处理器后,我们的 Node.js 应用程序的性能提升了 573%。这不仅仅是一个小小的优化,它从根本上改变了我们的 Node.js 应用程序在生产环境中的表现,并证明了单核性能优化对于任何 Node.js 应用程序的重要性。

Tip

对于 Node.js 生产部署的最佳实践,硬件选择至关重要。我们特意选择了 DataPacket 托管服务,因为他们支持 AMD Ryzen 处理器,因为 JavaScript 执行是单线程的,所以单核性能对于 Node.js 应用程序至关重要。

为什么单核性能优化对 Node.js 如此重要

我们从 Intel 迁移到 AMD Ryzen 的结果是:

性能提升如此显著,以至于我们现在认为 AMD Ryzen 处理器对于任何重要的 Node.js 生产部署都至关重要,无论您运行的是 Web 应用程序、API、微服务还是任何其他 Node.js 工作负载。

有关我们基础设施选择的更多详情,请查看:

Node.js 生产环境设置:我们的技术栈

我们的 Node.js 生产部署最佳实践包含基于多年生产经验的精心技术选择。以下是我们使用的技术以及这些选择适用于任何 Node.js 应用程序的原因:

软件包管理器:用于提高生产效率的 pnpm

我们使用的内容: pnpm(固定版本)

我们选择 pnpm 而不是 npm 和 yarn 作为我们的 Node.js 生产环境设置,因为:

  • CI/CD 流水线中的 安装速度更快
  • 通过硬链接节省磁盘空间**
  • 严格的依赖解析,防止幻影依赖
  • 生产部署中的 性能更佳

Note

作为 Node.js 生产部署最佳实践的一部分,我们固定了 pnpm 等关键工具的精确版本,以确保所有环境和团队成员机器上的行为一致。

实施细节:

Web 框架:用于现代 Node.js 生产的 Koa

我们使用的内容:

我们选择 Koa 而非 Express 作为 Node.js 生产基础架构,是因为它拥有先进的 async/await 支持和更简洁的中间件组合。我们的创始人 Nick Baugh 曾为 Express 和 Koa 做出过贡献,这让我们对这两个框架的生产应用有了深入的了解。

无论您构建的是 REST API、GraphQL 服务器、Web 应用程序还是微服务,这些模式都适用。

我们的实施示例:

后台作业处理:Bree 用于生产可靠性

我们使用:bree 调度程序

我们创建并维护 Bree 是因为现有的作业调度程序无法满足我们在 Node.js 生产环境中对工作线程支持和现代 JavaScript 特性的需求。这适用于任何需要后台处理、计划任务或工作线程的 Node.js 应用程序。

我们的实施示例:

错误处理:@hapi/boom 用于生产可靠性

我们使用的内容: @hapi/boom

我们在整个 Node.js 生产应用程序中使用 @hapi/boom 来构建结构化的错误响应。此模式适用于任何需要一致错误处理的 Node.js 应用程序。

我们的实施示例:

如何在生产环境中监控 Node.js 应用程序

我们在生产环境中监控 Node.js 应用程序的方法,是经过多年大规模运行应用程序的经验积累而不断演变的。我们实施多层监控,以确保任何类型的 Node.js 应用程序的可靠性和性能。

系统级 Node.js 生产监控

我们的核心实现: helpers/monitor-server.js

我们使用的内容: node-os-utils

我们的生产监控阈值(来自我们的实际生产代码):

  • 2GB 堆大小限制,并自动发出警报
  • 25% 内存使用率 警告阈值
  • 80% CPU 使用率 警告阈值
  • 75% 磁盘使用率 警告阈值

Warning

这些阈值适用于我们特定的硬件配置。在实施 Node.js 生产监控时,请查看我们的 Monitor-server.js 实现,以了解确切的逻辑并根据您的设置调整值。

Node.js 生产环境的应用级监控

我们的错误分类: helpers/is-code-bug.js

此帮助程序区分:

  • 需要立即关注的实际代码错误
  • 预期行为的用户错误
  • 我们无法控制的外部服务故障

此模式适用于任何 Node.js 应用程序 - Web 应用程序、API、微服务或后台服务。

我们的日志记录实现: helpers/logger.js

我们实施全面的字段编辑来保护敏感信息,同时在我们的 Node.js 生产环境中保持有用的调试功能。

应用程序特定监控

我们的服务器实现:

队列监控:我们实施 5GB 的队列限制和 180 秒的请求处理超时,以防止资源耗尽。这些模式适用于任何具有队列或后台处理的 Node.js 应用程序。

使用 PM2 健康检查进行 Node.js 生产监控

凭借多年的生产经验,我们利用 PM2 完善了 Node.js 生产环境的设置。PM2 健康检查对于维护任何 Node.js 应用程序的可靠性至关重要。

我们的 PM2 健康检查系统

我们的核心实现: jobs/check-pm2.js

我们通过 PM2 健康检查进行 Node.js 生产监控包括:

  • 通过 cron 调度每 20 分钟运行一次
  • 至少需要 15 分钟的正常运行时间,才能认定进程健康
  • 验证进程状态和内存使用情况
  • 自动重启失败的进程
  • 通过智能健康检查防止循环重启

Caution

根据 Node.js 生产部署的最佳实践,我们需要进程正常运行时间超过 15 分钟,才能将其视为健康进程,以避免出现重启循环。这可以防止进程在遇到内存或其他问题时发生级联故障。

我们的 PM2 生产配置

**我们的生态系统设置:**研究我们的服务器启动文件以进行 Node.js 生产环境设置:

无论您运行的是 Express 应用程序、Koa 服务器、GraphQL API 还是任何其他 Node.js 应用程序,这些模式都适用。

自动 PM2 部署

PM2 部署: ansible/playbooks/node.yml

我们通过 Ansible 自动化整个 PM2 设置,以确保所有服务器上的 Node.js 生产部署保持一致。

生产错误处理和分类系统

我们最有价值的 Node.js 生产部署最佳实践之一是适用于任何 Node.js 应用程序的智能错误分类:

我们的 isCodeBug 生产实现

来源:helpers/is-code-bug.js

此帮助程序为生产中的 Node.js 应用程序提供智能错误分类,以便:

  • 优先处理实际错误,而非用户错误
  • 通过关注实际问题来改进我们的事件响应
  • 减少预期用户错误导致的警报疲劳
  • 更好地理解应用程序而非用户生成的问题

此模式适用于任何 Node.js 应用程序 - 无论您是构建电子商务网站、SaaS 平台、API 还是微服务。

与我们的生产日志集成

我们的记录器集成: helpers/logger.js

我们的记录器使用 isCodeBug 来确定警报级别和字段编辑,确保我们收到有关实际问题的通知,同时过滤掉 Node.js 生产环境中的噪音。

了解有关我们的错误处理模式的更多信息:

使用 v8-profiler-next 和 cpupro 进行高级性能调试

我们使用高级性能分析工具来分析堆快照,并调试生产环境中的 OOM(内存溢出)问题、性能瓶颈以及 Node.js 内存问题。这些工具对于任何遇到内存泄漏或性能问题的 Node.js 应用程序都至关重要。

我们针对 Node.js 生产的分析方法

我们推荐的工具:

  • v8-profiler-next - 用于生成堆快照和 CPU 配置文件
  • cpupro - 用于分析 CPU 配置文件和堆快照

Tip

我们结合使用 v8-profiler-next 和 cpupro,为 Node.js 应用程序创建了一套完整的性能调试工作流程。这种组合有助于我们识别内存泄漏、性能瓶颈,并优化生产代码。

我们如何实现堆快照分析

我们的监控实现: helpers/monitor-server.js

我们的生产监控功能包括在内存超过阈值时自动生成堆快照。这有助于我们在 OOM 问题导致应用程序崩溃之前进行调试。

关键实施模式:

  • 当堆大小超过 2GB 阈值时自动创建快照
  • 基于信号的分析,用于生产环境中的按需分析
  • 保留策略,用于管理快照存储
  • 与我们的清理作业集成,用于自动维护

性能调试工作流程

研究我们的实际实施:

对于堆快照分析:

  1. 安装 v8-profiler-next 用于生成快照
  2. 使用 cpupro 分析生成的快照
  3. 实现监控阈值,类似于我们的monitor-server.js
  4. 设置自动清理 来管理快照存储
  5. 创建信号处理程序 用于在生产环境中进行按需分析

对于 CPU 分析:

  1. 在高负载期间生成 CPU 性能分析数据
  2. 使用 cpupro 进行分析以识别瓶颈
  3. 关注热点路径和优化机会
  4. 监控性能改进前后的变化

Warning

生成堆快照和 CPU 配置文件可能会影响性能。我们建议实施限制,并且仅在调查特定问题或维护期间启用配置文件。

与我们的生产监控集成

我们的分析工具与我们更广泛的监控策略相结合:

  • 基于内存/CPU 阈值自动触发
  • 检测到性能问题时集成警报
  • 历史分析,用于跟踪随时间推移的性能趋势
  • 与应用程序指标关联,用于全面调试

这种方法帮助我们识别和解决内存泄漏,优化热代码路径,并在 Node.js 生产环境中保持稳定的性能。

Node.js 生产基础设施安全

我们通过 Ansible 自动化为 Node.js 生产基础架构实施全面的安全保护。以下实践适用于任何 Node.js 应用程序:

Node.js 生产的系统级安全性

我们的 Ansible 实现: ansible/playbooks/security.yml

我们针对 Node.js 生产环境采取的主要安全措施:

  • 禁用交换分区,以防止敏感数据写入磁盘
  • 禁用核心转储,以防止包含敏感信息的内存转储
  • 阻止 USB 存储设备,以防止未经授权的数据访问
  • 调整内核参数,兼顾安全性和性能

Warning

在实施 Node.js 生产部署最佳实践时,如果您的应用程序超出可用内存,禁用交换空间可能会导致内存不足导致应用程序终止。我们会仔细监控内存使用情况,并适当调整服务器大小。

Node.js 应用程序的应用程序安全性

我们的日志字段编辑: helpers/logger.js

我们从日志中删除了敏感字段,包括密码、令牌、API 密钥和个人信息。这不仅保护了用户隐私,还确保在任何 Node.js 生产环境中都能进行调试。

基础设施安全自动化

我们为 Node.js 生产环境完成的 Ansible 设置:

我们的安全内容

详细了解我们的安全方法:

Node.js 应用程序的数据库架构

我们使用针对 Node.js 应用程序优化的混合数据库方法。这些模式可适用于任何 Node.js 应用程序:

Node.js 生产的 SQLite 实现

我们使用的内容:

我们的配置: ansible/playbooks/sqlite.yml

我们在 Node.js 应用程序中使用 SQLite 来存储用户特定数据,因为它提供:

  • 按用户/租户进行数据隔离
  • 单用户查询性能更佳
  • 简化备份和迁移
  • **与共享数据库相比,降低复杂性

此模式适用于 SaaS 应用程序、多租户系统或任何需要数据隔离的 Node.js 应用程序。

用于 Node.js 生产的 MongoDB 实现

我们使用的内容:

我们的设置实现: helpers/setup-mongoose.js

我们的配置: config/mongoose.js

我们在 Node.js 生产环境中使用 MongoDB 来存储应用程序数据,因为它提供:

  • 灵活的模式,适用于不断变化的数据结构
  • 更佳的复杂查询性能
  • 水平扩展功能
  • 丰富的查询语言

Note

我们的混合方法针对特定用例进行了优化。请研究代码库中实际的数据库使用模式,以了解此方法是否适合您的 Node.js 应用程序需求。

Node.js 生产后台作业处理

我们围绕 Bree 构建了后台作业架构,以实现可靠的 Node.js 生产部署。这适用于任何需要后台处理的 Node.js 应用程序:

我们的 Bree 服务器生产设置

我们的主要实现: bree.js

我们的 Ansible 部署: ansible/playbooks/bree.yml

生产作业示例

健康监测: jobs/check-pm2.js

清理自动化: jobs/cleanup-tmp.js

我们所有的工作: 浏览我们的完整职位目录

这些模式适用于需要以下功能的任何 Node.js 应用程序:

  • 计划任务(数据处理、报告、清理)
  • 后台处理(图像大小调整、电子邮件发送、数据导入)
  • 健康监测与维护
  • CPU 密集型任务的工作线程利用率

我们用于 Node.js 生产环境的作业调度模式

研究我们的作业目录中的实际作业调度模式,以了解:

  • 我们如何在 Node.js 生产环境中实现类似 cron 的调度
  • 我们的错误处理和重试逻辑
  • 我们如何使用工作线程执行 CPU 密集型任务

生产 Node.js 应用程序的自动维护

我们实施主动维护,以防止常见的 Node.js 生产问题。以下模式适用于任何 Node.js 应用程序:

我们的清理实施

来源:jobs/cleanup-tmp.js

我们对 Node.js 生产应用程序的自动化维护目标是:

  • 超过 24 小时的临时文件
  • 超出保留期限的日志文件
  • 缓存文件和临时数据
  • 不再需要的已上传文件
  • 性能调试中的堆快照

这些模式适用于生成临时文件、日志或缓存数据的任何 Node.js 应用程序。

Node.js 生产环境的磁盘空间管理

我们的监控阈值: helpers/monitor-server.js

  • 后台处理的队列限制
  • 75% 磁盘使用率警告阈值
  • 超过阈值时自动清理

基础设施维护自动化

我们用于 Node.js 生产的 Ansible 自动化:

Node.js 生产部署实施指南

研究我们的实际代码以获得生产最佳实践

从这些关键文件开始设置 Node.js 生产环境:

  1. 配置config/index.js
  2. 监控helpers/monitor-server.js
  3. 错误处理helpers/is-code-bug.js
  4. 日志记录helpers/logger.js
  5. 进程健康jobs/check-pm2.js

从我们的博客文章中学习

我们针对 Node.js 生产的技术实施指南:

Node.js 生产基础设施自动化

我们用于 Node.js 生产部署的 Ansible 剧本:

我们的案例研究

我们的企业实施:

结论:Node.js 生产部署最佳实践

我们的 Node.js 生产基础设施证明 Node.js 应用程序可以通过以下方式实现企业级可靠性:

  • 久经考验的硬件选择(AMD Ryzen 处理器,单核性能优化 573%)
  • 久经考验的 Node.js 生产监控,具有特定阈值和自动响应功能
  • 智能错误分类,可提升生产环境中的事件响应能力
  • 使用 v8-profiler-next 和 cpupro 进行高级性能调试,可预防 OOM
  • 通过 Ansible 自动化进行全面的安全加固
  • 混合数据库架构,针对应用需求进行了优化
  • 自动化维护,可预防常见的 Node.js 生产问题

关键要点:研究我们实际的实现文件和博客文章,而不是遵循通用的最佳实践。我们的代码库为 Node.js 生产部署提供了实际的模式,可以适用于任何 Node.js 应用程序 - Web 应用、API、微服务或后台服务。

Node.js 生产的完整资源列表

我们的核心实施文件

我们的服务器实现

我们的基础设施自动化

我们的技术博客文章

我们的企业案例研究