Node.js看起来很有趣,但我必须错过一些东西 - 不是Node.js只调整为在单个进程和线程上运行吗?
那么它如何扩展多核CPU和多CPU服务器?毕竟,尽可能快速地制作单线程服务器,但是对于高负载我想要使用多个CPU.同样可以使应用程序更快 - 似乎今天的方式是使用多个CPU并并行化任务.
Node.js如何适应这张图片?它的想法是以某种方式分发多个实例或什么?
似乎所有节点woker进程都在运行,就像它正在执行同一应用程序的新副本一样.但是希望保留节点集群中所有节点工作者(子进程)共享的一些变量.有一个简单的方法吗?
我有一个使用集群的服务器,并使用socke.IO工作我正在使用粘性会话,但我的房间有问题(我不知道我的方式是否是最好的选择):集群实例化流程,每个流程都有特定数量的房间.
我将一些用户连接到房间(只有一个进程)的方法是使用路由,用户访问页面,当他尝试与Socket.io建立连接时,我检查URL并使用该信息插入他在一个房间里.
我的问题是使用集群实现此服务器我不能将用户插入特定的房间,因为有些房间只存在于特定的进程中,粘性会话将他放在另一个进程中.如何将用户置于另一个进程中的房间?此外,使用只能查看他在服务器中的进程路由,我想显示页面中的每个房间.
我已经阅读过有关Redis-Adapter的内容,但我没有在使用Socket.io + Cluster(Sticky-session + redis-adapter)+ rooms的github上找到解决方案.
按照我的代码分享我所做的事情:
//Cluster.Master with simplified Code
if (cluster.isMaster) {
var workers = [];
// Spawn workers.
for (var i = 0; i < num_processes; i++) {
spawn(i);
}
// Create the outside facing server listening on our port.
var server = net.createServer({
pauseOnConnect: true
}, function(connection) {
// We received a connection and need to pass it to the appropriate
// worker. Get …Run Code Online (Sandbox Code Playgroud) 任何人都知道如何在Windows上运行Node Cluster?我无法在网上找到任何文章,似乎无法解决这个问题:
events.js:160
throw er; // Unhandled 'error' event
^
Error: write ENOTSUP
at exports._errnoException (util.js:1007:11)
at ChildProcess.target._send (internal/child_process.js:634:20)
at ChildProcess.target.send (internal/child_process.js:521:19)
at sendHelper (cluster.js:751:15)
at send (cluster.js:534:12)
at cluster.js:509:7
at SharedHandle.add (cluster.js:99:3)
at queryServer (cluster.js:501:12)
at Worker.onmessage (cluster.js:449:7)
at ChildProcess.<anonymous> (cluster.js:765:8)
Run Code Online (Sandbox Code Playgroud)
而代码......
if (cluster.isMaster) {
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('online', (worker) => {
console.log('Worker ' + worker.process.pid + ' is online');
});
cluster.on('exit', (worker, code, signal) => {
console.log(`Worker ${worker.process.pid} died …Run Code Online (Sandbox Code Playgroud) 如果我创建一个包含4个worker(我的应用程序的4个实例)的节点集群应用程序,我应该使用mySQL池还是mysql池集群?如果我使用池,它将为每个应用程序创建一个池但如果我使用池集群,它将为每个应用程序创建4个池(总共16个).这是一个很好的实现还是会降低性能?
首先,让我们为mysql数据库创建配置文件(重要的是我创建db worker的这个文件的最后一部分):
DBconfig.js
'use strict'
const mysql = require('mysql'),
workers = process.env.WORKERS || require('os').cpus().length,
cluster = require('cluster');
//Local Database Settings
const local_settings = {
user : 'user',
host : '127.0.0.1',
password : 'pass',
database : 'dbname',
debug : false,
dateStrings: true,
connectionLimit : 10,
defaultSelector : 'RR',
multipleStatements : true,
removeNodeErrorCount: 1
};
let poolCluster = module.exports = mysql.createPoolCluster( local_settings );
//here I make one db worker for each app worker
for(let i = 0; i < …Run Code Online (Sandbox Code Playgroud) 在我使用群集模块的node.js应用程序中,我间歇性地看到这样的错误:
events.js:71
throw er; // Unhandled 'error' event
^
Error: read ECONNRESET
at errnoException (net.js:863:11)
at TCP.onread (net.js:524:19)
Run Code Online (Sandbox Code Playgroud)
这降低了我的整个应用程序,到目前为止,我能够处理这些的唯一方法是绑定一个process.on('uncaughtException').我想找出根本原因,但上面的堆栈跟踪是没用的.
有没有办法弄清楚导致这些异常的原因是什么?
我应该注意到,我只在群集主服务器中看到这些,而不是工作者,这使我怀疑它们与群集模块在分配与工作人员的连接方面发挥作用的方式有关.
我知道我可以使用Nodes cluster模块来创建几个所有服务于同一套接字连接的工作者(例如来自docs):
var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
// Fork workers.
for (var i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', function(worker, code, signal) {
console.log('worker ' + worker.process.pid + ' died');
});
} else {
// Workers can share any TCP connection
// In this case its a HTTP server
http.createServer(function(req, res) {
res.writeHead(200);
res.end("hello world\n");
}).listen(8000);
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我不是为同一个连接服务而是希望每个工作者都运行自己的服务器,每个服务器都在一个单独的端口上监听呢?
我在单机上使用websockets/ws 。它工作正常。我想在多核和多个实例上水平扩展它。对于多核,我尝试使用pm2,它似乎工作得很好。
第一个问题:这是最好的方法还是合适的方法?这是我使用 pm2 的测试代码
// ws-server.js
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 3131 });
var pid = process.pid + ''
console.log('process pid: '+ pid)
wss.on('connection', function connection(ws) {
ws.on('message', function incoming(message) {
if (message === 'get-pid') {
ws.send('pid-' + pid)
} else {
var matched = pid === message ? 'old friends' : 'strangers'
ws.send([pid, message, 'we are ' + matched].join(', '))
}
});
ws.send('first time')
});
Run Code Online (Sandbox Code Playgroud)
和客户端 websocket 实例
// …Run Code Online (Sandbox Code Playgroud) const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
console.log(`Master ${process.pid} is running`);
// Fork workers.
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', (worker, code, signal) => {
console.log(`worker ${worker.process.pid} died`);
});
} else {
// Workers can share any TCP connection
// In this case it is an HTTP server
var sticky = require('sticky-session');
var express = require('express');
var app = express();
app.get('/', function (req, res) { …Run Code Online (Sandbox Code Playgroud) 使用 Node.JS 和cluster模块。
我试图了解多个分叉子进程如何在同一个端口上侦听。
例如,使用cluster模块我们可以这样做:
const port = 443;
...
if (cluster.isMaster) {
for(let i = 0; i < numCPUs; i++)
{
cluster.fork();
}
...
}
else // Forked child processes:
{
...
https.createServer({
key: fs.readFileSync('server.key'),
cert: fs.readFileSync('server.cert')
}, app)
.listen(port, () => {
console.log(`HTTPS Listening on port ${port}`);
});
}
Run Code Online (Sandbox Code Playgroud)
此代码派生多个进程,所有进程都调用listen同一个端口。我不清楚所有进程如何绑定同一个端口并且仍然能够确定哪个进程获取端口流量。这实际上是一种错觉,而是主进程实际上是唯一一个绑定端口并将请求随机传递给分叉子进程的进程?(如果是这种情况,是不是对性能有影响?)
感谢您帮助我了解所有子进程如何同时侦听同一端口。
请注意,此示例在 Windows 机器上运行,但如果我理解正确,它与 Windows 和 Linux 兼容。
node-cluster ×10
node.js ×10
javascript ×4
websocket ×2
fork ×1
node-mysql ×1
pm2 ×1
port ×1
socket.io ×1
worker ×1