您现在的位置是:网站首页 > 进程监控文章详情
进程监控
陈川
【
Node.js
】
33845人已围观
4460字
进程监控的基本概念
进程监控是Node.js应用开发中不可或缺的一环。它涉及对运行中进程的状态、资源使用情况和异常行为的实时跟踪与管理。在服务器环境中,进程可能因为内存泄漏、CPU过载或未捕获异常而崩溃,有效的监控能帮助开发者快速定位问题。
Node.js的process
对象提供了基础监控能力。通过它,可以获取进程ID、运行时间、内存占用等信息:
console.log(`Process PID: ${process.pid}`);
console.log(`Uptime: ${process.uptime()} seconds`);
console.log(`Memory Usage: ${JSON.stringify(process.memoryUsage())}`);
内置模块监控方案
process模块的核心功能
process.memoryUsage()
返回的对象包含:
rss
:常驻内存大小heapTotal
:已申请堆内存heapUsed
:当前使用堆内存external
:C++对象占用内存
setInterval(() => {
const mem = process.memoryUsage();
console.log(`Heap Used: ${(mem.heapUsed / 1024 / 1024).toFixed(2)} MB`);
}, 1000);
事件循环监控
使用perf_hooks
模块可以测量事件循环延迟:
const { monitorEventLoopDelay } = require('perf_hooks');
const h = monitorEventLoopDelay({ resolution: 20 });
h.enable();
setInterval(() => {
console.log(`EventLoop Delay: ${h.mean.toFixed(2)}ms`);
h.reset();
}, 5000);
第三方监控工具
PM2的进阶功能
安装PM2后,可以通过编程接口获取详细数据:
const pm2 = require('pm2');
pm2.connect(err => {
pm2.list((err, processes) => {
processes.forEach(proc => {
console.log(`App: ${proc.name} CPU: ${proc.monit.cpu}%`);
});
});
});
Clinic.js诊断套件
使用Clinic.js进行火焰图分析:
clinic flame -- node server.js
生成的火焰图可以直观显示函数调用关系和CPU时间消耗。
自定义指标收集
实现HTTP请求监控
使用http
模块扩展监控:
const http = require('http');
const server = http.createServer();
server.on('request', (req, res) => {
const start = process.hrtime();
res.on('finish', () => {
const diff = process.hrtime(start);
console.log(`Request ${req.url} took ${diff[0] * 1000 + diff[1] / 1e6}ms`);
});
});
进程健康检查端点
创建专用的监控接口:
app.get('/health', (req, res) => {
const health = {
status: 'UP',
uptime: process.uptime(),
memory: process.memoryUsage(),
load: os.loadavg()
};
res.json(health);
});
异常处理与自动恢复
未捕获异常处理
使用domain
模块创建隔离域:
const domain = require('domain');
const d = domain.create();
d.on('error', err => {
console.error('Domain caught:', err);
server.close();
process.exit(1);
});
d.run(() => {
require('./unstable-module');
});
子进程监控
监控子进程的退出状态:
const { spawn } = require('child_process');
const child = spawn('node', ['worker.js']);
child.on('exit', (code, signal) => {
console.log(`Child exited with code ${code}`);
if (code === 1) {
// 自动重启逻辑
setTimeout(() => spawn('node', ['worker.js']), 1000);
}
});
分布式系统监控
聚合多个服务的指标
使用statsd
客户端发送指标:
const StatsD = require('node-statsd');
const client = new StatsD({
host: 'metrics.example.com'
});
setInterval(() => {
client.gauge('memory.heap', process.memoryUsage().heapUsed);
}, 5000);
日志集中收集
配置Winston进行日志聚合:
const winston = require('winston');
const { Loggly } = require('winston-loggly-bulk');
winston.add(new Loggly({
token: "YOUR_TOKEN",
subdomain: "YOUR_SUBDOMAIN",
tags: ["NodeJS"],
json: true
}));
winston.error('Process threshold exceeded', { pid: process.pid });
性能优化实践
内存泄漏检测
使用heapdump
生成堆快照:
const heapdump = require('heapdump');
setInterval(() => {
if (process.memoryUsage().heapUsed > 500 * 1024 * 1024) {
heapdump.writeSnapshot(`/tmp/heap-${Date.now()}.heapsnapshot`);
}
}, 30000);
CPU分析
通过v8-profiler
收集CPU数据:
const profiler = require('v8-profiler-next');
profiler.startProfiling();
setTimeout(() => {
const profile = profiler.stopProfiling();
profile.export()
.pipe(fs.createWriteStream(`cpuprofile-${Date.now()}.cpuprofile`))
.on('finish', () => profile.delete());
}, 10000);
容器环境适配
Kubernetes健康检查
实现Liveness和Readiness探针:
// Liveness Probe
app.get('/liveness', (req, res) => {
if (app.locals.healthy) {
res.status(200).send('OK');
} else {
res.status(500).end();
}
});
// Readiness Probe
app.get('/readiness', (req, res) => {
if (db.connected && redis.connected) {
res.status(200).send('OK');
} else {
res.status(503).end();
}
});
Docker资源限制处理
检测容器内存限制:
const fs = require('fs');
function getDockerMemoryLimit() {
try {
return parseInt(fs.readFileSync('/sys/fs/cgroup/memory/memory.limit_in_bytes'));
} catch {
return os.totalmem();
}
}
console.log(`Container Memory Limit: ${getDockerMemoryLimit() / 1024 / 1024}MB`);