Node.js 应用高 CPU 占用率的分析方法

Node.js 应用高 CPU 占用率的分析方法
最新回答
我不会写诗

2022-11-02 05:46:46

分析 Node.js 应用高 CPU 占用率可采用以下方法,涵盖本地开发和生产环境的不同场景:

本地开发环境分析方法
  1. 使用 Chrome DevTools 进行 CPU 分析

    启动应用时添加 --inspect 标志:

    node --inspect your-app.js

    在 Chrome 浏览器访问 chrome://inspect,点击应用下方的 inspect 按钮。

    在 DevTools 中选择 Memory 标签页,点击 Record CPU Profile 按钮开始分析。

    执行负载测试后停止记录,查看火焰图定位高耗时函数。

  2. 命令行工具辅助分析

    使用 top 或 htop 快速定位高 CPU 占用的 Node 进程。

    通过 ps -aux | grep node 获取进程 PID 后,使用 perf 或 strace 进行底层分析。

生产环境分析方法
  1. 按需采集 CPU Profile(推荐)

    使用 Node.js 内置 inspector 模块或 inspector-api 包装库,避免全量调试模式的高开销。

    示例代码(NestJS 框架)

    import { Controller, Post } from '@nestjs/common';import { promisify } from 'util';import Inspector from 'inspector-api';const profileRecordTime = 10000; // 记录时长10秒@Controller('/profile')export class ProfileController { @Post('/cpu') async cpu() { setImmediate(async () => { const inspector = new Inspector({ storage: { type: 'fs' } }); await inspector.profiler.enable(); await inspector.profiler.start(); await promisify(setTimeout)(profileRecordTime); await inspector.profiler.stop(); console.log('CPU profile saved to temp dir'); await inspector.profiler.disable(); }); return true; }}

    通过 HTTP 端点触发采集:

    curl -X POST
    http://your-server/profile/cpu
  2. 信号触发采集(无 HTTP 暴露)

    监听系统信号(如 SIGUSR1)触发分析:

    process.on('SIGUSR1', async () => { const inspector = new Inspector({ storage: { type: 'fs' } }); await inspector.profiler.start(); await promisify(setTimeout)(profileRecordTime); await inspector.profiler.stop();});

    通过 kill 命令发送信号:

    kill -USR1 <node-pid>
  3. 堆内存分析(辅助排查)

    替换 profiler 为 heap 模块采集堆快照:

    process.on('SIGUSR2', async () => { const inspector = new Inspector({ storage: { type: 'fs' } }); await inspector.heap.startSampling(); await promisify(setTimeout)(profileRecordTime); await inspector.heap.stopSampling();});

    触发命令:

    kill -USR2 <node-pid>
结果分析步骤
  1. 定位热点函数

    采集的 .cpuprofile 文件可用 Chrome DevTools 或 speedscope 等工具打开。

    火焰图中宽度较大的函数块代表高 CPU 占用。

  2. 优化建议

    同步阻塞操作:检查是否有未优化的循环或同步 I/O 操作。

    事件循环延迟:使用 process.hrtime() 监控事件循环阻塞时间。

    内存泄漏:结合堆快照分析对象保留情况。

注意事项
  • 生产环境安全:确保采集端点受权限控制,避免暴露敏感数据。
  • 资源开销:单次采集建议不超过 30 秒,避免影响服务稳定性。
  • 临时文件:定期清理生成的 .cpuprofile 文件,防止磁盘占满。
示例:采集的 CPU Profile 文件路径

通过上述方法,可系统化定位 Node.js 应用的高 CPU 占用问题,平衡排查效率与生产环境稳定性。