Ubuntu上Node.js运行缓慢的排查与优化清单
一 快速定位瓶颈
- 先看系统资源:用htop/glances观察CPU、内存、I/O、负载,确认是否因资源不足导致卡顿。
- 再看应用本身:用node --inspect配合Chrome DevTools做CPU热点分析;或用node --prof生成分析文件,定位耗时函数与调用栈。
- 关注事件循环:在关键路径加入hrtime与memoryUsage埋点,识别长任务与内存抖动。
- 检查日志:使用winston/pino输出结构化日志,配合grep/awk/sed统计P95/P99响应时间与错误率,找出慢接口与异常。
- 线上持续观测:用PM2 monit或接入New Relic/Datadog/Prometheus+Grafana,建立指标与链路追踪,便于回溯。
二 系统层面优化
- 提升文件描述符上限:临时执行ulimit -n 65535;永久写入**/etc/security/limits.conf**(如:* soft nofile 65535,hard nofile 65535),避免“Too many open files”。
- 优化网络参数:编辑**/etc/sysctl.conf**,常见值如net.core.somaxconn=4096、net.ipv4.tcp_max_syn_backlog=4096、net.ipv4.ip_local_port_range=1024 65535、net.ipv4.tcp_tw_reuse=1、net.ipv4.tcp_fin_timeout=30,执行sudo sysctl -p生效,改善高并发连接与短连接回收。
- 存储与硬件:优先使用SSD,并视情况增加内存,降低I/O与GC压力。
- 反向代理与静态资源:用Nginx承载静态文件、压缩与长连接,减轻Node进程负担并提升吞吐。
三 Node.js运行时与代码优化
- 版本与依赖:用nvm安装并切换到最新稳定版Node.js;按需更换npm镜像源加速安装。
- 充分利用多核:使用cluster模块或PM2集群模式(如pm2 start app.js -i max)跑满CPU。
- 避免阻塞事件循环:I/O一律异步;对CPU密集任务用Worker Threads/子进程或拆分到独立服务;大数据用Streams减少内存占用。
- 内存与V8:通过**–max-old-space-size**设置堆上限,减少频繁GC;优化数据结构与对象复用,避免内存泄漏。
- 数据库与缓存:为查询加索引、使用连接池、尽量批量操作;对热点数据用Redis/Memcached做缓存。
- 高效库与算法:选择性能更好的库(如fast-json-stringify替代JSON.stringify),并优化关键路径算法与数据结构。
四 生产部署与监控建议
- 进程管理:用PM2启动与守护进程,开启集群与监控(如pm2 monit),支持零停机重启与日志聚合。
- 可观测性:接入New Relic/Datadog或自建Prometheus+Grafana,完善指标、日志与链路追踪,结合性能钩子/perf_hooks做关键路径埋点。
- 日志治理:使用winston/pino输出JSON日志,配置logrotate做按日轮转与压缩,便于分析与归档。
- 变更与回归:任何内核/运行时/依赖调整先在预发布环境压测与A/B验证,再灰度上线,持续观察P95/P99与错误率。
五 常见场景与对策速查表
| 场景 |
可能原因 |
快速对策 |
| 高并发下吞吐上不去 |
仅用单进程、连接队列小 |
启用cluster/PM2集群;调大somaxconn与tcp_max_syn_backlog |
| 接口偶发很慢或超时 |
同步阻塞、长任务 |
排查并改为异步;将CPU密集任务移入Worker Threads/子进程 |
| 内存持续增长、频繁GC |
内存泄漏、对象滥用 |
用**–prof定位;优化数据结构;设置合理–max-old-space-size** |
| 大文件/大响应慢 |
一次性读写占用内存 |
改用Streams分块处理与传输 |
| 数据库查询慢 |
缺索引、无连接池 |
加索引、启用连接池、合并请求与批量操作 |
| 静态资源与反向代理压力大 |
Node直出静态文件 |
用Nginx托管静态资源、开启压缩与长连接 |
| 包安装/构建很慢 |
官方npm源慢 |
切换npm镜像源加速安装与依赖拉取 |