英文:
Redirect HTTP upgrade to a websocket on another instance
问题
以下是您提供的内容的中文翻译:
我使用Node集群,在每个工作进程上都有一个运行中的WebSocket服务器。主进程有一个运行中的HTTP服务器。
在主HTTP服务器上,我想要一个HTTP升级调用的实现,它将连接调用者到特定的WebSocket。
为什么?我希望能够将用户连接到正确的WebSocket,但我想通过一个单一的入口点localhost:8000来实现。连接到localhost:8000可能会将您无缝地连接到localhost:8001。
我的想法是调用Upgrade并带有参数,例如:
wscat -c ws://localhost:8000/?id=5
这个调用应该传递到主进程,主进程将转发此升级调用并与localhost:8005建立连接。
我以为我可以简单地使用worker.send()将升级参数转发给工作进程,但这确实不起作用,我在工作进程中接收到的对象缺少很多东西,这可能是我不了解的JS基础知识。
这是我的天真实现:
var http = require('http');
var cluster = require('cluster')
var ws = require('ws');
var NumberOfInstances = 5;
if (cluster.isMaster) {
var forks = []
for (var i=0; i < NumberOfInstances; i++) {
forks.push(cluster.fork());
}
server = http.createServer((req, res) => {
res.writeHead(200);
}).listen(8000);
server.on('upgrade', (request, socket, head) => {
var params = new URL(`https://localhost:8000${request.url}`);
var id = parseInt(params.searchParams.get('clusterId')) - 1;
// How do I forward upgrade??
forks[id].send({r: request, s: socket, h: head});
})
} else {
portStr = `800${cluster.worker.id}`;
wss = new ws.WebSocketServer({
port: portStr
});
wss.on('connection', (ws, request) => {
console.log(`${cluster.worker.id} got connection.`);
})
process.on('message', masterMessage => {
// This absolutely doesn't work.
wss.handleUpgrade(masterMessage.r, masterMessage.s, masterMessage.h, (ws) => {
wss.emit('connection', ws, masterMessage.r);
})
})
}
希望这有助于理解您的代码和问题。如果您有任何进一步的问题,请随时提出。
英文:
I use Node cluster, on each worker there's a running websocket server. Master has a HTTP server running.
On the Master HTTP server I want a HTTP Upgrade call implementation, that will connect the caller to a specific web socket.
Why? I want to be able to connect user to a correct websocket, but I want to do it through a single entry point being localhost:8000. Connecting to localhost:8000 might connect you to localhost:8001 seamlessly.
My idea was to call Upgrade with a parameter like:
wscat -c ws://localhost:8000/?id=5
This call should go to the Master, and master would forward this upgrade call and make connection with localhost:8005.
I thought I could simply forward the upgrade params to the worker with worker.send(), but this doesn't really work, objects I receive in the worker miss a lot of things, it's probably some basics of JS I don't know about.
Here's my naive implementation:
var http = require('http');
var cluster = require('cluster')
var ws = require('ws');
var NumberOfInstances = 5;
if (cluster.isMaster) {
var forks = []
for (var i=0; i < NumberOfInstances; i++) {
forks.push(cluster.fork());
}
server = http.createServer((req, res) => {
res.writeHead(200);
}).listen(8000);
server.on('upgrade', (request, socket, head) => {
var params = new URL(`https://localhost:8000${request.url}`);
var id = parseInt(params.searchParams.get('clusterId')) - 1;
// How do I forward upgrade??
forks[id].send({r: request, s: socket, h: head});
})
} else {
portStr = `800${cluster.worker.id}`;
wss = new ws.WebSocketServer({
port: portStr
});
wss.on('connection', (ws, request) => {
console.log(`${cluster.worker.id} got connection.`);
})
process.on('message', masterMessage => {
// This absolutely doesn't work.
wss.handleUpgrade(masterMessage.r, masterMessage.s, masterMessage.h, (ws) => {
wss.emit('connection', ws, masterMessage.r);
})
})
}
答案1
得分: 2
根据文档,你需要将套接字处理程序作为worker.send
方法的第二个参数发送。
所以你应该这样做,
forks[id].send({ headers: request.headers, method: request.method, head: head }, socket); //socket is in second argument
在你的子进程message
事件处理程序中,这样做,
process.on('message', (request, socket) => {
wss.handleUpgrade(request, socket, request.head, (ws) => {
wss.emit('connection', ws, request);
})
})
查看这个示例,了解如何将套接字对象作为参数传递。
英文:
According to docs, you are required to send the socket handler as a second argument to the worker.send
method.
So you should do this instead,
forks[id].send({ headers: request.headers, method: request.method, head: head }, socket); //socket is in second argument
and in your child message
event handler, do this,
process.on('message', (request,socket) => {
wss.handleUpgrade(request, socket, request.head, (ws) => {
wss.emit('connection', ws, request);
})
})
Look at this example to see how to pass socket object as an argument.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论