提问者:小点点

通过节点代理服务器运行的基于Socket.IO的应用程序,每当一个套接字断开时,就会断开所有套接字的连接


我用node.jsexpresssocket.io制作了一个基本的聊天应用程序。它与socket.io的教程聊天应用没有太大区别,它只是在连接的客户机之间发出事件。当我在服务器的3001端口上运行它时,它工作得很好。

然后,我使用node-http-proxy制作了一个代理服务器应用程序,它监听端口80,并根据请求的url将流量重定向到我在不同端口上运行的各种独立节点应用程序。很直截了当。但有东西坏了。每当有人断开连接时,每个插座都会断开并重新连接。这对我的聊天应用来说很糟糕,因为它有基于连接的事件。客户端控制台都显示:

到“ws://[some socket info]”的WebSocket连接失败:连接在接收握手响应之前关闭

下面是我认为的代码的重要部分。

var http = require('http');
var httpProxy = require('http-proxy');

//create proxy template object with websockets enabled
var proxy = httpProxy.createProxyServer({ws: true});

//check the header on request and return the appropriate port to proxy to
function sites (req) {
    //webapps get their own dedicated port
    if (req == 'mychatwebsite.com') {return 'http://localhost:3001';}
    else if (req == 'someothersite.com') {return 'http://localhost:3002';}
    //static sites are handled by a vhost server on port 3000
    else {return 'http://localhost:3000';}
}

//create node server on port 80 and proxy to ports accordingly
http.createServer(function (req, res) {
    proxy.web(req, res, { target: sites(req.headers.host) });
}).listen(80);
/*
...other modules
*/
var express = require("express");
var app = exports.app = express(); //I probably don't need "exports.app" anymore
var http = require("http").Server(app);
var io = require("socket.io")(http);

io.on("connection", function (socket) {
  /*
  ...fun socket.on and io.emit stuff
  */
  socket.on("disconnect", function () {
    //say bye
  });
});

http.listen(3001, function () {
  console.log("listening on port 3001");
});

现在,从我在socket.io站点上读到的内容来看,我可能需要使用一些东西来通过代理服务器传送套接字流量。我以为node-http-proxy通过{ws:true}选项为我实现了这一点,正如它在文档中所说的那样,但显然它的工作方式并不像我想象的那样。socket.io提到了三个不同的内容:

    基于节点的内置群集模块的
  • 粘滞会话
  • socket.io-redis,它允许单独的socket.io实例彼此对话
  • socket.io-发射器,它允许socket.io与非socket.io进程对话

我完全不知道这是什么意思。我无意中编写的代码超出了我的技能水平,我不知道这些工具中的哪一个能解决我的问题(如果有的话),甚至不知道问题的真正原因是什么。

必须道歉:我是node.js的新手,请原谅我。

也是必须的:我知道像nginx这样的其他应用程序可以解决我的很多问题,但我的目标是在我开始使用新的工具之前学习和理解如何使用这套工具。而且,我使用的应用程序越少越好。


共1个答案

匿名用户

我认为您的直觉是正确的,需要“通过”代理服务器的套接字流量。为了建立websocket,客户机使用特殊的upgrade头发出HTTP请求,向服务器发出切换协议的信号(RFC 6455)。在node中,发生这种情况时,http.server实例会发出upgrade事件,如果未处理该事件,则会立即关闭连接。

您需要侦听http服务器上的upgrade事件并对其进行处理:

var proxy = httpProxy.createProxyServer({ws: true})
var http = http.createServer(/* snip */).listen(80)

// handle upgrade events by proxying websockets
// something like this
http.on('upgrade', function (req, socket, head) {
  proxy.ws(req, socket, head, {target:sites(req.headers.host)})
})

有关更多信息,请参阅升级事件上的node文档和node-http-proxy文档。