Ubuntu 上 Node.js 常见性能瓶颈与定位路径
一 常见瓶颈概览
二 快速定位路径
top/htop(CPU 单核是否打满)、vmstat 1(si/so、cs、r)、iostat -x 1(await、svctm、util)、ss -s/netstat -s(连接数、重传)、lsof | wc -l(句柄)。process.memoryUsage()、--inspect/Chrome DevTools CPU Profiler、node --prof + llprof/speedscope 火焰图、clinic.js doctor/flame。pm2 monit/pm2 list、内置 perf_hooks 记录关键路径耗时。journalctl -u your-node-service -f、tail -f logs/app.log、pm2 logs app --lines 200。UnhandledPromiseRejectionWarning、MaxListenersExceededWarning、DeprecationWarning、ENOMEM heap out of memory,这些常指向 Promise 未处理、事件监听泄漏、依赖过时、内存上限 等根因。ab/wrk/autocannon 做基线压测;在压测同时采集火焰图与系统指标,定位是 CPU 计算、I/O 等待 还是 外部依赖。三 典型症状与对策
| 症状 | 高概率根因 | 快速验证 | 对策 |
|---|---|---|---|
| P95/P99 高、吞吐低 | 事件循环阻塞(同步计算/大 JSON/正则回溯) | CPU Profiler 火焰图“长条” | 将重计算移出事件循环(Worker Threads/子进程/流),优化算法与数据大小 |
| 内存持续增长、GC 长暂停 | 缓存失控、闭包引用、大对象未释放 | process.memoryUsage()、堆快照 |
设 TTL/容量上限、弱引用/缓存分层、分批处理、必要时 --max-old-space-size 仅作权宜 |
| 数据库/Redis 耗时占比高 | 缺索引、N+1、连接池小、超时 | 慢查询日志、连接数监控 | 加索引、批量/合并、连接池与超时调优、引入缓存与降级 |
| 偶发 OOM | 内存泄漏、一次性加载大文件/大表 | 重启后 RSS 曲线、堆快照对比 | 修复泄漏、流式处理、分页/游标、限流与背压 |
| 连接排队/失败 | 句柄/连接数上限、短连接、池化不足 | ss -s、错误日志“EMFILE/ECONNRESET” |
复用连接、调大池与 ulimit -n、开启 keep-alive、优化超时 |
| 单核打满、多核空闲 | 仅单实例运行 | htop 单核 100% |
使用 cluster/PM2 cluster 多进程,按核数扩展 |
| 磁盘/网络 I/O 打满 | 同步日志、无轮转、大响应体、未压缩 | iostat/nload、日志写入延迟 |
异步日志、启用 logrotate、压缩与分页、CDN/压缩中间件 |
四 Ubuntu 与运维侧的优化要点
--max-old-space-size 缓解 OOM,但优先通过 代码/架构 优化;容器场景设置合理 内存/CPU 限额 与 优雅停机。以上路径能在 Ubuntu 环境下较快定位 Node.js 的性能瓶颈:先用系统/运行时工具确认是 CPU/内存/I/O/连接/依赖 哪一类,再结合日志与火焰图落到具体代码路径与配置项进行优化。