如何将套接字传递给节点中的集群
Posted
技术标签:
【中文标题】如何将套接字传递给节点中的集群【英文标题】:How to pass socket to cluster in node 【发布时间】:2016-05-10 02:52:52 【问题描述】:我想要一个多进程节点。工作人员正在监听客户端连接。我需要将套接字传递给主进程,因为主进程向客户端发出消息。 Worker 还需要通过套接字向客户端发送消息。
Socket 是一个循环对象,不能传递给主进程。
我的代码:
const cluster = require('cluster');
const http = require('http');
var io = require('socket.io');
var users;
var clients = ;
if (cluster.isMaster)
function messageHandler(msg)
if (msg.usersarray)
usersarray = msg.usersarray;
console.log(usersarray);
else if(msg.socket)
clients[usersarray["manu"][0]] = msg.socket;
clients[usersarray["manu"][0]].emit("hola","hola");
// Start workers and listen for messages containing notifyRequest
const numCPUs = require('os').cpus().length;
for (var i = 0; i < numCPUs; i++)
cluster.fork();
Object.keys(cluster.workers).forEach((id) =>
cluster.workers[id].on('message', messageHandler);
);
else
// Create server & socket
var server = http.createServer(function(req, res)
// Send html headers and message
res.writeHead(404, 'Content-Type': 'text/html');
res.end('<h1>Aw, snap! 404</h1>');
);
server.listen(3000);
io = io.listen(server);
// Add a connect listener
io.sockets.on('connection', function(socket)
var hs = socket.handshake;
console.log("socket connected");
if(users == undefined)
users = ;
if(hs.query.usuario != undefined)
if(users[hs.query.usuario] == undefined)
users[hs.query.usuario] = new Array();
users[hs.query.usuario].push(socket.id); // connected user with its socket.id
clients[socket.id] = socket; // add the client data to the hash
process.send( usersarray: users);
process.send( socket: socket);
// Disconnect listener
socket.on('disconnect', function()
console.log('Client disconnected.');
);
);
in line process.send( socket: socket); Node js 报错“TypeError: Converting circular structure to JSON”
-我使用了一些模块来转换圆形对象但不工作。
-我尝试传递套接字 id,然后在主进程中,用这个 id 创建了新的套接字,但我不知道要使用它。
有没有可能将套接字从工作进程传递给主进程?
节点js版本:v5.5.0
【问题讨论】:
【参考方案1】:嗯,我认为您尝试做的事情是不可能的。当您创建集群时,这意味着您创建了只能通过管道进行通信的单独进程(主进程 + 工作进程)。
通过管道交谈意味着他们只能互相发送字符串。 process.send
尝试使用 JSON.stringify 将 javascript 对象序列化为 JSON(--> 从中生成字符串)。例如 JSON 不能有函数、圆等。我刚刚检查了 socket
对象,它非常复杂并且包含函数(例如 socket.emit()
),因此您不能只是将其序列化并通过管道发送。
也许您可以查看this 或this 了解如何使用集群 WebSockets。
这似乎不是很微不足道。也许您可以将 CPU 密集型任务传递给一些工作进程(通过集群或只是自己生成它们),将结果发送回主节点,让他与主进程进行所有通信客户?
【讨论】:
【参考方案2】:我了解您向集群中的所有节点工作进程广播的目的,尽管您不能这样发送套接字组件,但有一种解决方法可以达到该目的。我将尝试用一个例子来解释:
第 1 步:当客户端操作需要广播时:
Child.js(已分叉的进程):
socket.on("BROADCAST_TO_ALL_WORKERS", function (data)
process.send(cmd : 'BROADCAST_TO_ALL_WORKERS', message :data.message);
)
第 2 步:在集群创建方面
Server.js(集群分叉发生的地方):
if (cluster.isMaster)
for (var i = 0; i < numCPUs; i++)
var worker = cluster.fork();
worker.on('message', function (data)
if (data.cmd === "BROADCAST_TO_ALL_WORKERS")
console.log(server_debug_prefix() + "Server Broadcast To All, Message : " + data.message + " , Reload : " + data.reload + " Player Id : " + data.player_id);
Object.keys(cluster.workers).forEach(function(id)
cluster.workers[id].send(cmd : "BROADCAST_TO_WORKER", message : data.message);
);
);
cluster.on('exit', function (worker, code, signal)
var newWorker = cluster.fork();
newWorker.on('message', function (data)
console.log(data);
if (data.cmd === "BROADCAST_TO_ALL_WORKERS")
console.log(data.cmd,data);
Object.keys(cluster.workers).forEach(function(id)
cluster.workers[id].send(cmd : "BROADCAST_TO_WORKER", message : data.message);
);
);
);
else
//Node Js App Entry
require("./Child.js");
第三步:在子进程中广播
-> 把这个放在 Child.js 中的 io.on("connection") 之前
process.on("message", function(data)
if(data.cmd === "BROADCAST_TO_WORKER")
io.sockets.emit("SERVER_MESSAGE", message: data.message, reload: data.reload, player_id : data.player_id );
);
我希望它清楚。如果它令人困惑,请发表评论......我会尽力说清楚。
【讨论】:
以上是关于如何将套接字传递给节点中的集群的主要内容,如果未能解决你的问题,请参考以下文章