Node.js集群环境下如何让函数与定时任务仅执行一次?
Hey there! Both of your questions boil down to the same core issue: when using Node.js cluster, every worker process you fork will execute your application code (unless you explicitly guard it). That’s why your function and cron job are running multiple times—once per worker, plus potentially once in the master process if you don’t restrict it. Let’s fix this!
Solution Core: Use cluster.isMaster to Identify the Master Process
The master process is the single parent process that spawns all your workers. We can use the cluster.isMaster flag to run our one-time code only in the master process, while letting workers handle your regular application logic (like serving API requests).
Fix for Question 1: Run a Function Once Despite Multiple CPU Cores
Simply wrap your function call inside the if (cluster.isMaster) block. This ensures it runs exactly once, regardless of how many CPU cores you have.
Example code:
const cluster = require('cluster'); const numCPUs = require('os').cpus().length; // Your function that needs to run once function mySingleRunFunction() { console.log(`This runs ONLY ONCE! Master PID: ${process.pid}`); // Add your business logic here } if (cluster.isMaster) { // First, run your one-time function mySingleRunFunction(); // Then fork your worker processes for (let i = 0; i < numCPUs; i++) { cluster.fork(); console.log(`Forked worker with PID: ${cluster.workers[i+1].process.pid}`); } // Optional: Restart workers if they exit cluster.on('exit', (worker) => { console.log(`Worker ${worker.process.pid} died. Restarting...`); cluster.fork(); }); } else { // Worker process logic (e.g., start your Express/Koa server) console.log(`Worker ${process.pid} is running`); // Your app's business code here }
Fix for Question 2: Prevent Cron Jobs/Functions from Running Multiple Times in Your Cluster
Looking at your existing cluster code, you just need to move your cron job and function calls into the master process block. Here’s how to modify your code:
const cluster = require('cluster'); // Don't forget to import cluster! const numCPUs = require('os').cpus().length; const cron = require('node-cron'); // If using node-cron for scheduled tasks if (cluster.isMaster) { // Fork workers as before for (var i = 0; i < numCPUs; i++) { cluster.fork(); console.log(`Forked worker PID: ${process.pid}`); } cluster.on('exit', function (worker, code, signal) { console.log('worker ' + worker.process.pid + ' died'); // Optional: Auto-restart failed workers cluster.fork(); }); // -------------------------- // Add your one-time code HERE // -------------------------- // Run your function once function myCriticalTask() { console.log('Executing critical task once from master process'); // Your task logic here } myCriticalTask(); // Start your cron job (only in master) cron.schedule('0 0 * * *', () => { console.log('Daily cron job running from master process'); // Cron job logic here }); } else { // Worker process: Handle your app's regular traffic/tasks console.log(`Worker ${process.pid} initialized`); // Example: Start your HTTP server // const app = require('./app'); // app.listen(3000); }
Key Notes
- Never put one-time code in the worker block: Workers are spawned multiple times, so any code here will run once per worker.
- Master process role: The master process is ideal for managing workers and running singleton tasks (like cron jobs, database migrations, or one-time setup). It won’t handle regular application traffic unless you explicitly tell it to.
- Alternative for isolated tasks: If you don’t want the master process to handle any singleton logic, you can spawn a separate standalone process using
child_process.spawn()for your cron job/function. But this adds complexity, so thecluster.isMasterapproach is preferred for most cases.
内容的提问来源于stack exchange,提问作者Nishant Khandelwal

