Mev*_*via 7 javascript multithreading node.js socket.io
当我启动我的应用程序时node app.js,运行的进程只有一个线程.无论运行的时间越长,为该进程制作的线程越多.问题是,当我想执行这样的特定代码时:
var io = require('socket.io')(process.env.PORT);
Run Code Online (Sandbox Code Playgroud)
它失败是因为信号是从多个线程发送的,因此代码未成功执行.
简单测试,如果这样做:
var io = require('socket.io')(9001);
var io = require('socket.io')(9002);
var io = require('socket.io')(9003);
var io = require('socket.io')(9004);
Run Code Online (Sandbox Code Playgroud)
它工作正常,但这段代码:
var cPort = 9001;
setInterval(function() {
var io = require('socket.io')(cPort);
cPort++;
}, 1000 * 60 * 2); // 1 sec * 60 seconds * 2 = 2 minutes interval
Run Code Online (Sandbox Code Playgroud)
不会被执行,因为2分钟后节点将有许多线程,他们都试图执行代码 - 因此你会看到error: address in use.
因此,尽管运行相同文件的多线程进程,我怎么能强制节点只执行一次这个代码?
06.11.2017编辑----
澄清问题:
我在问题中的意思是,我没有资源问题,如果我一次启动所有服务器(例如40台服务器),它们都已成功启动并无限期地工作.如果我只启动一个服务器,然后运行在需要时自动启动更多的代码,则会出现问题.在那一点上我总是看到address in use错误,显然地址在代码执行的时刻没有被使用.目前,我必须在周末手动启动更多服务器,因为有更多人在一周的其他日子使用服务和更少的服务器,我想创建基于人口启动和关闭服务器的自动化系统.
这是服务器启动的代码:
var cp = require('child_process'),
servers = [],
per_server = config.per_server,
check_servers = function(callback) {
for(var i = 0; i < servers.length; i++) {
callback(i, servers[i]);
}
};
this.add_server = function(port) {
var server = {
port: port,
load: 0,
process: cp.fork(__dirname + '/../server_instance.js', [], {
env: {
port: port
}
})
};
server.process.on('message', function(message) {
server.load = message.load;
});
servers.push(server);
};
this.find_server = function() {
var min = Infinity,
port = false;
check_servers(function(index, details) {
if(details.load < min) {
min = details.load;
port = details.port;
}
});
return port;
};
Run Code Online (Sandbox Code Playgroud)
现在,如果我controller.add_server()连续执行40次,它将正确启动40台服务器,但如果我这样做:
var start_port = 3185;
setInterval(function() {
var min = Infinity;
check_servers(function(index, details) {
if(details.load < min) {
min = details.load;
}
});
if(min > config.per_server) {
controller.add_server(start_port);
start_port++;
}
}, 5000);
Run Code Online (Sandbox Code Playgroud)
我在第二次,第三次或第四次服务器创建时得到随机错误,该地址已被使用.
07.11.2017编辑----
正如建议我尝试使用以下库进行端口扫描/查找:
只使用第一个我能够启动至少2个服务器,这是我使用的代码:
setInterval(function() {
var min = Infinity;
check_servers(function(index, details) {
if(details.load < min) {
min = details.load;
}
});
if(min > per_server) {
_self.add_server();
}
}, 5000);
var portfinder = require('portfinder');
portfinder.basePort = 3185;
this.add_server = function() {
portfinder.getPortPromise()
.then((port) => {
console.log('port found', port);
var server = {
port: port,
load: 0,
process: cp.fork(__dirname + '/../server_instance.js', [], {
env: {
port: port
}
})
};
server.process.on('message', function(message) {
server.load = message.load;
});
servers.push(server);
})
.catch((err) => {
console.log('error happened');
});
};
Run Code Online (Sandbox Code Playgroud)
经过多次测试后,看起来我可以启动2台服务器然后随机,在第三次或第四次尝试时崩溃.很明显,问题更深入,然后端口查找,这个库只告诉我我已经知道的东西,我知道打开了什么端口,并且我仔细检查脚本之前是否会尝试使用手动netstat -anp | grep PORT命令启动服务器.
所以很清楚,问题不在于找到打开的端口,从结果的角度来看,似乎节点试图从单个命令多次启动服务器.
跟进编辑----
添加server_instance.js代码:
var io = require('socket.io')(process.env.port),
connections_current = 0,
connections_made = 0,
connections_dropped = 0;
io.on('connection', function(socket) {
connections_current++;
connections_made++;
// ... service logic here, not relevant (like query db, send data to users etc)
socket.on('disconnect', function() {
connections_current--;
connections_dropped++;
});
});
setInterval(function() {
process.send({
load: connections_current
});
}, 5000);
Run Code Online (Sandbox Code Playgroud)
08.11.2017编辑----
我正在测试许多解决问题的解决方案,我观察到了这种情况:
在mac osx上进行本地测试,我可以在服务器上生成最多3000个连接.错误永远不会发生,节点有1 process和6 threads路由器文件.通过3000个连接,我甚至可以生成200台服务器而没有任何问题
在linux debian上的服务器测试,我生成2毫升到服务器的连接.当我连接所有人节点6 processes和10 threads for every process路由器文件时,错误总是发生在第3或第4服务器实例上.
这显然是问题的根源,我拥有的容量越多,节点产生的进程就越多,并且在尝试启动新服务器时它会更快地重叠.