将HTTP升级重定向到另一个实例上的WebSocket。

huangapple go评论88阅读模式
英文:

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(&#39;http&#39;);
var cluster = require(&#39;cluster&#39;)
var ws = require(&#39;ws&#39;);
var NumberOfInstances = 5;
if (cluster.isMaster) {
var forks = []
for (var i=0; i &lt; NumberOfInstances; i++) {
forks.push(cluster.fork());
}
server = http.createServer((req, res) =&gt; {
res.writeHead(200);
}).listen(8000);
server.on(&#39;upgrade&#39;, (request, socket, head) =&gt; {
var params = new URL(`https://localhost:8000${request.url}`);
var id = parseInt(params.searchParams.get(&#39;clusterId&#39;)) - 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(&#39;connection&#39;, (ws, request) =&gt; {
console.log(`${cluster.worker.id} got connection.`);
})
process.on(&#39;message&#39;, masterMessage =&gt; {
// This absolutely doesn&#39;t work. 
wss.handleUpgrade(masterMessage.r, masterMessage.s, masterMessage.h, (ws) =&gt; {
wss.emit(&#39;connection&#39;, 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(&#39;message&#39;, (request,socket) =&gt; {
wss.handleUpgrade(request, socket, request.head, (ws) =&gt; {
wss.emit(&#39;connection&#39;, ws, request);
})
})

Look at this example to see how to pass socket object as an argument.

huangapple
  • 本文由 发表于 2023年6月15日 05:00:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/76477500.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定