Linux 下 Node.js 性能监控实操指南

做性能监控,最怕的不是没有工具,而是工具太多不知道怎么搭。今天咱们把Linux下Node.js性能监控这件事拆开揉碎了说,从底层指标到上层告警、从日常查看到故障排查,一步到位。
一 监控体系与分层
把监控拆开来看,其实很清晰:系统层、进程层、应用层、日志与链路层、可视化告警层——这五层搭起来,才能形成一个完整的闭环。少任何一层,都容易在定位问题时两眼一抹黑。
常见的工具,我帮你列在这儿,随便翻翻看——
- 系统层:top/htop、vmstat、iostat、free、df、sar、nmon、atop、perf、strace、tcpdump/Wireshark、Nethogs/iftop。CPU、内存、磁盘I/O、网络,再到系统调用与抓包,全涵盖了。
- 进程层:PM2。它不只是进程管理,资源监控、日志聚合、自动重启,都管。
- 应用层:Node.js内置的perf_hooks/process、v8-profiler、heapdump、node --inspect/--prof、Chrome DevTools。搞应用级性能分析,这几个是主力。
- 日志与链路层:winston/morgan负责输出结构化日志,ELK Stack/Graylog/Splunk负责收、查、告。
- 可视化与告警层:Prometheus + Grafana、New Relic、Datadog、Uptime Kuma。自建或买商业方案,看团队需求和预算。
- 服务编排与可靠性:systemd。让进程常驻、自动拉起、日志集中,省心不少。
二 快速上手步骤
先说进程与日志。用PM2启动和守护服务是最简单的一条路:
- 安装:
npm i -g pm2 - 启动:
pm2 start app.js --name my-api - 查看状态:
pm2 status - 实时监控资源:
pm2 monit - 实时日志:
pm2 logs my-api - 设置自动重启和内存阈值:
pm2 set pm2restartdelay 1000、pm2 set pm2maxrestarts 5、pm2 set pm2memoryrestart 100M。这一步对于防止内存泄漏长期拖垮系统,非常关键。
系统资源这块,日常巡检几行命令就够:
- 进程资源:
top/htop - 系统整体:
vmstat 1 - 磁盘:
iostat -x 1 - 内存:
free -m - 磁盘空间:
df -h - CPU历史和实时:
sar -u 1 3 - 综合监控:
nmon/atop
这些都是经验证的老牌命令,可靠、轻量、不花哨。
运行与故障排查方面,推荐两条路:
- 用systemd把服务跑起来,日志集中到journal:
journalctl -u my-app,重启原因、stdout/stderr一眼可见。 - 远程调试用
node --inspect或node --inspect-brk,然后接Chrome DevTools的Performance面板,录制一段就能看到热点。CPU热点分析用node --prof生成日志,再用node --prof-process处理。内存泄漏就上heapdump,生成快照后扔进DevTools的Memory面板,比对快照,引用链一目了然。
三 关键指标与采集方法
下面这张表,建议你收藏。它把每个维度该看什么、怎么采、用什么工具,都串起来了。
| 维度 | 关键指标 | 采集方式/工具 | 说明 |
|---|---|---|---|
| CPU | 进程CPU%、系统负载 | top/htop、vmstat、sar -u | 识别计算密集与多核利用情况 |
| 内存 | RSS、堆使用、堆上限、GC行为 | PM2 monit、process.memoryUsage()、--prof/DevTools | 关注堆增长与频繁GC |
| 事件循环 | 延迟、阻塞时长 | 应用埋点或APM | 定位长任务/回调堆积 |
| 请求性能 | P50/P95/P99、吞吐、错误率 | prom-client + Prometheus/Grafana、New Relic/Datadog | 以路由/状态码维度聚合 |
| 文件系统 | 磁盘使用率、IOPS、吞吐 | df、iostat | 日志/上传导致的I/O压力 |
| 网络 | 带宽、连接数、重传 | nload/iftop、Nethogs、tcpdump/Wireshark | 发现连接风暴与慢客户端 |
| 依赖服务 | DB查询耗时、慢查询 | DB慢查询日志、EXPLAIN | SQL与索引优化依据 |
举个例子,用prom-client暴露出HTTP请求的时延直方图,你可以像这样写:
const promClient = require('prom-client');
const httpRequestDurationMicroseconds = new promClient.Histogram({
name: 'http_request_duration_ms',
help: 'Duration of HTTP requests in ms',
labelNames: ['method', 'route', 'code'],
buckets: [0.1, 5, 15, 50, 100, 200, 300, 400, 500]
});
app.use((req, res, next) => {
const start = Date.now();
res.on('finish', () => {
const duration = Date.now() - start;
httpRequestDurationMicroseconds
.labels(req.method, req.route?.path || req.path, res.statusCode)
.observe(duration);
});
next();
});
然后在Prometheus里配上抓取任务,再到Grafana里拉出P50/P95/P99曲线,设置告警阈值。这一步做完,接口性能波动就能即时感知了。
四 可视化与告警落地
落地方式主要有三种,看团队情况选:
- 自建可观测性栈:Prometheus抓取Node.js应用指标(prom-client)和系统指标,Grafana做可视化仪表盘和阈值告警。对数据主权要求高、预算有限的团队,这条路最踏实。
- 商业APM:New Relic或Datadog,分布式追踪、错误跟踪、数据库和外部调用分析全包了,开箱即用。想快速提升可观测性覆盖,这个选择最省心。
- 可用性监控:Uptime Kuma,轻量自托管,支持HTTP/HTTPS/TCP/Ping探针,通知渠道覆盖Telegram、Discord、Slack。站点存活监测,一个就够了。
- 日志中枢:用winston/morgan输出结构化日志,然后灌进ELK、Graylog或Splunk,做检索、聚合和告警。
五 排障流程与优化建议
遇到问题了,别慌,按症状找工具,一步步来。
- CPU飙高:先上top或htop,定位到是哪个进程在吃资源。然后用
perf top -p找热点函数,用strace -p看系统调用占比。Node侧,用-c --prof配合DevTools或火焰图,找到JS执行热点。这步走完,代码层面的瓶颈基本上就暴露了。 - 内存泄漏:用PM2 monit或process.memoryUsage()持续观察堆增长趋势。趋势不对,就生成heapdump快照,用DevTools的Memory面板对比,锁定泄漏对象和引用链。这一步,耐心和对比是关键。
- 请求变慢/超时:从应用埋点或APM看P95/P99和错误率。DB侧开慢查询日志,用EXPLAIN分析索引是否合理。必要时,tcpdump抓包分析握手延迟、重传率和长尾。很多时候,问题出在数据库这一层,而不是Node本身。
- 磁盘/网络瓶颈:iostat查IOPS和await,df看容量是否吃紧,iftop或Nethogs定位哪个进程在占带宽。结合业务日志和DB慢查询,判断是写入放大还是外部依赖拥堵。
最后,优化方向上,有几个核心原则:
- 避免阻塞事件循环——大计算任务拆分,该用Worker Threads或子进程就别省。
- 合理使用缓存(内存或Redis),减少重复计算和I/O。
- 优化SQL与索引,批量写入、连接池、超时设置别忽略。
- 控制并发与背压,设置合理的请求超时和重试策略。
把这些做到位,性能监控就算真正闭环了。