Node.js 带集群的周期性任务
Node.js periodic tasks with clustering
我是 运行 StrongLoop 的环回 API 服务器,处于生产模式。这意味着 master 进程创建了与你的 CPU 有多少个核心一样多的 worker。所以 master process 只控制 workers 而从不执行你的代码。
我的目的是每次只执行一次周期性任务,因为现在它在所有 4 个 worker 上运行。
除了 cron 或 Redis 类存储中的 'key lock' 之外,还有什么建议吗?
在 iojs 和节点 v0.12 中,可以执行 exclusive socket binding。这可以用作类似于基于文件系统的方法的锁定形式。两者的方法相同:
attempt exclusive access to resource
if success:
perform task
else:
do not perform task
使用套接字,你会做这样的事情:
net.createServer().on('error', function(err) {
console.log('did not get lock', err);
}).listen({ port: 4321, exclusive: true }, function() {
singleProcessTask();
this.close();
});
请注意 exclusive: true
只有集群模式才需要,因为它默认共享套接字。
与fs.open类似:
fs.open('lock.file', 'wx', function(err, fd) {
if (err) {
console.log('did not get lock', err);
} else{
singleProcessTask();
fs.close(fd, function(err) {
// insert error handling here
fs.unlink('lock.file', function(err) {
// insert error handling here
});
});
});
在这两种情况下,如果您的任务非常快并且您的进程的计时器计划略有不同,则可能会出现竞争条件。在这些情况下,该任务仍将一次仅由一个进程执行,但它可能会在每个计划周期内处理多次,具体取决于您如何实施计划。
编辑: 更具说明性的例子
var net = require('net');
var HOUR = 60*60*1000;
setInterval(myTask, HOUR);
function myTask() {
locked(function() {
// task code here
});
}
function locked(fn) {
net.createServer().on('error', function(err) {
console.log('did not get lock', err);
}).listen({ host: '127.0.0.1', port: 4321, exclusive: true }, function() {
fn();
this.close();
});
}
我是 运行 StrongLoop 的环回 API 服务器,处于生产模式。这意味着 master 进程创建了与你的 CPU 有多少个核心一样多的 worker。所以 master process 只控制 workers 而从不执行你的代码。
我的目的是每次只执行一次周期性任务,因为现在它在所有 4 个 worker 上运行。
除了 cron 或 Redis 类存储中的 'key lock' 之外,还有什么建议吗?
在 iojs 和节点 v0.12 中,可以执行 exclusive socket binding。这可以用作类似于基于文件系统的方法的锁定形式。两者的方法相同:
attempt exclusive access to resource
if success:
perform task
else:
do not perform task
使用套接字,你会做这样的事情:
net.createServer().on('error', function(err) {
console.log('did not get lock', err);
}).listen({ port: 4321, exclusive: true }, function() {
singleProcessTask();
this.close();
});
请注意 exclusive: true
只有集群模式才需要,因为它默认共享套接字。
与fs.open类似:
fs.open('lock.file', 'wx', function(err, fd) {
if (err) {
console.log('did not get lock', err);
} else{
singleProcessTask();
fs.close(fd, function(err) {
// insert error handling here
fs.unlink('lock.file', function(err) {
// insert error handling here
});
});
});
在这两种情况下,如果您的任务非常快并且您的进程的计时器计划略有不同,则可能会出现竞争条件。在这些情况下,该任务仍将一次仅由一个进程执行,但它可能会在每个计划周期内处理多次,具体取决于您如何实施计划。
编辑: 更具说明性的例子
var net = require('net');
var HOUR = 60*60*1000;
setInterval(myTask, HOUR);
function myTask() {
locked(function() {
// task code here
});
}
function locked(fn) {
net.createServer().on('error', function(err) {
console.log('did not get lock', err);
}).listen({ host: '127.0.0.1', port: 4321, exclusive: true }, function() {
fn();
this.close();
});
}