我正在运行一个集群 Node.js 应用程序,并尝试监视每个单独工作进程的 CPU 使用百分比。我使用集群模块来充分利用多核服务器,大约有 8 个工作进程处理请求。
我的目标是跟踪每个工作人员的 CPU 使用率百分比,以便我可以了解每个工作人员随着时间的推移消耗了多少 CPU。
我尝试过的
我最初使用 prom-client 库设置了一个 Gauge 指标来公开 Prometheus 和 Grafana 的指标。我的方法是:
这是我用来计算 CPU 使用百分比的代码的相关部分:
import http from 'http';
import cluster from 'cluster';
import os from 'os';
import { app, startApolloServer } from './app.js';
import prisma from './prisma/index.js';
import 'dotenv/config';
import { handleUncaughtErrors } from './middleware/errorHandlerMiddleware.js';
import client from 'prom-client';
const SERVER_PORT = process.env.PORT || 8080;
const numWorkers = parseInt(process.env.WORKER_COUNT || `${Math.max(1, Math.floor(os.cpus().length / 2))}`, 10);
console.log(`Number of workers: ${numWorkers}`);
// Initialize Prometheus metrics collection for each worker
client.collectDefaultMetrics();
// Gauge metric for manual per-worker CPU usage tracking
const cpuUsageGauge = new client.Gauge({
name: 'nodejs_worker_cpu_usage',
help: 'CPU usage percentage of each Node.js worker',
labelNames: ['worker_id'], // Add worker ID as a label
});
if (cluster.isPrimary) {
console.info(`Primary ${process.pid} is running`);
// Fork workers.
for (let i = 0; i < numWorkers; i++) {
cluster.fork();
}
// Listen for dying workers and restart them.
cluster.on('exit', (worker) => {
console.warn(`Worker ${worker.process.pid} died. Starting a new one...`);
cluster.fork();
});
} else {
const startServer = async () => {
try {
const httpServer = http.createServer(app);
await startApolloServer(app);
httpServer.listen(SERVER_PORT, () => {
console.info(`🚀 Worker ${process.pid} started at http://localhost:${SERVER_PORT}/graphql`);
});
handleUncaughtErrors(httpServer, prisma);
// Set up CPU usage monitoring
let previousCpuUsage = process.cpuUsage();
const availableCores = os.cpus().length;
setInterval(() => {
const currentCpuUsage = process.cpuUsage();
const userTime = currentCpuUsage.user - previousCpuUsage.user;
const systemTime = currentCpuUsage.system - previousCpuUsage.system;
const totalCpuTime = userTime + systemTime;
// Convert to percentage: use interval time and number of cores
const usagePercent = (totalCpuTime / (5e6 * availableCores)) * 100;
// Update the gauge metric for this worker
cpuUsageGauge.set({ worker_id: process.pid.toString() }, usagePercent);
// Store current CPU usage for the next interval comparison
previousCpuUsage = currentCpuUsage;
}, 5000);
} catch (error) {
console.error('Failed to start server', error);
process.exit(1);
}
};
startServer().catch((error) => {
console.error('Failed to start server', error);
process.exit(1);
});
// Gracefully close Prisma connection on app exit
process.on('SIGTERM', async () => {
console.log(`Worker ${process.pid} received SIGTERM, shutting down gracefully...`);
await prisma.$disconnect();
process.exit(0);
});
process.on('SIGINT', async () => {
console.log(`Worker ${process.pid} received SIGINT, shutting down gracefully...`);
await prisma.$disconnect();
process.exit(0);
});
}
问题 我在 Grafana 中看到的结果与我根据其他 CPU 使用指标(例如 Docker 统计数据)所期望的结果不一致。有时,我看到的值极低(低于 1%),而其他时候,值似乎被夸大了。
我需要什么 如何在考虑多个 CPU 核心的情况下准确计算集群 Node.js 设置中每个工作线程的 CPU 使用百分比?理想情况下,我希望以清晰的百分比形式查看每个工作线程的 CPU 使用率,类似于您在 Docker 统计数据中看到的情况,但在 Node.js 中是每个工作线程。
任何有关如何正确计算的帮助或澄清将不胜感激!
根据文档,要将
prom-client
与 cluster
模块一起使用,您应该将默认的全局注册表替换为聚合注册表:
默认情况下,指标是从全局注册表聚合的。要使用不同的注册表,请从工作进程中调用 client.AggregatorRegistry.setRegistries(registryOrArrayOfRegistries)。
您可以这样对待它 - 每个工作人员都使用指标公开自己的地图,并且要从单个“应用程序”收集它们,您应该将它们全部组合起来。这是文档建议的示例。
prom-client
库默认收集了
一些基本指标,包括
process.cpuUsage()
,请考虑检查它们是否符合您的需求。这很可能就是您想要的。