您现在的位置是:网站首页 > 进程监控文章详情

进程监控

进程监控的基本概念

进程监控是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`);

上一篇: 零停机重启

下一篇: 容器化部署

我的名片

网名:~川~

岗位:console.log 调试员

坐标:重庆市-九龙坡区

邮箱:cc@qdcc.cn

沙漏人生

站点信息

  • 建站时间:2013/03/16
  • 本站运行
  • 文章数量
  • 总访问量
微信公众号
每次关注
都是向财富自由迈进的一步