我的目标是创建一个父进程,无限期地将消息流式传输到子进程。为了测试这一点,我尝试使用以下代码将150M消息发送给不执行任何操作的子进程。
代码:
// After 20M messages i get:
// FATAL ERROR: CALL_AND_RETRY_2 Allocation failed - process out of memory
var cp = require('child_process');
var xrange = require('xrange');
var maxChildren = require('os').cpus().length;
var util = require('util');
require('ofe').call();
var childError = function(err) {
console.log('Error: ' + err);
};
var childExit = function(code, signal) {
console.log('Exit Code: ' + code);
console.log('Exit Signal: ' + signal);
};
var childClose = function(code, signal) {
console.log('Close Code: ' + code);
console.log('Close Signal: ' + signal);
};
var childDisconnect = function() {
console.log('Disconnect');
};
var childMessage = function(msg, handle) {
console.log('Msg: ' + msg);
};
var createChild = function(){
var child = cp.fork("./child");
child.on('error', childError);
child.on('exit', childExit);
child.on('close', childClose);
child.on('disconnect', childDisconnect);
child.on('message', childMessage);
console.log("Child Created: " + child.pid);
return child;
}
var createChildren = function(){
var children = [];
xrange(maxChildren).each(function(i) {
children[i] = createChild();
});
return children;
}
var sendMessages = function(children) {
xrange(150000000).each(function(num) {
var idx = num % maxChildren;
if (num % 1000000 == 0) {
console.log(num);
}
children[idx].send(num);
});
};
process.on('message', function(msg) {});
由于此代码是异步的,因此父进程会将所有消息发送给子进程,而无需等待它们被处理,这似乎会使客户端过载。我相信解决方案是从客户端发回消息,以便在处理后“拉”下一个数字。假设这是答案,我有一个跟进问题。
1)我想写这个但是我不确定如何将xrange转换为生成器而没有屈服(no-harmony nodejs),是否有回调解决方案? :
function getNextNumber(){
//pull the next available number from the 150M
}
child.on('message',function(msg) {
child.send(getNextNumber());
});
如果我只是想迭代,这似乎就是这样:https://stackoverflow.com/a/5784473/1578888。
如果我正确地阅读这个替代答案,似乎将xrange调用实现为真正的生成器是不可能的预和谐:https://stackoverflow.com/a/7442013/1578888
这是我最终使用的代码(也将server.js重命名为parent.js):
var cp = require('child_process');
var xrange = require('xrange');
var maxChildren = require('os').cpus().length;
var util = require('util');
require('ofe').call();
var childError = function(err) {
console.log('Error: ' + err);
};
var childExit = function(code, signal) {
console.log('Exit Code: ' + code);
console.log('Exit Signal: ' + signal);
};
var childClose = function(code, signal) {
console.log('Close Code: ' + code);
console.log('Close Signal: ' + signal);
};
var childDisconnect = function() {
console.log('Disconnect');
};
var childMessage = function(msg, handle) {
//no output anymore!
//console.log('Msg: ' + msg);
};
var createChild = function(){
var child = cp.fork("./child.js");
child.on('error', childError);
child.on('exit', childExit);
child.on('close', childClose);
child.on('disconnect', childDisconnect);
child.on('message', childMessage);
console.log("Child Created: " + child.pid);
return child;
}
var getNextFn = (function () {
var i = 0
return function(cb) {
i = i + 1;
if (i < 150000000) {
return i;
} else {
return null;
}
}
})();
var createChildren = function(){
var children = [];
xrange(maxChildren).each(function(i) {
var child = createChild();
child.on('message', function(msg) {
var next = getNextFn();
if (next) {
if (next % 1000000 == 0) {
console.log(next + " " + new Date().toISOString());
}
child.send(next);
} else {
child.kill();
}
});
children[i] = child;
});
return children;
}
var c = createChildren();
process.on('message', function(msg) {
process.send({});
});
process.send({});