通过节点代理服务器运行的基于Socket.io的应用程序在断开连接时断开所有套接字

时间:2015-02-20 12:30:28

标签: node.js sockets socket.io node-http-proxy

我使用node.jsexpresssocket.io制作了一个基本聊天应用。它与socket.io的tutorial chat app没有什么不同,它只是在连接的客户端之间发出事件。当我在服务器上的端口3001上运行它时,它工作正常。

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

  

WebSocket连接到' ws:// [某些套接字信息] '失败:在收到握手响应之前关闭连接

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

代理server.js

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);

聊天app.js

/*
...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's site上阅读的内容,我可能需要使用一些东西通过我的代理服务器来承载套接字流量。我认为node-http-proxy通过their docs中的{ws: true}选项为我做了这个,但显然它并没有像我想象的那样工作。 socket.io提到了三个不同的东西:

我完全不知道这意味着什么或做了什么。我不小心在这里编写了高于我的技能水平的编码,我不知道这些工具中的哪一个会解决我的问题(如果有的话),甚至我的问题的原因是什么。

强制道歉:我是node.js的新手,所以请原谅我。

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

1 个答案:

答案 0 :(得分:4)

我认为你对需要“通过代理服务器承载套接字流量”的直觉是正确的。为了建立websocket,客户端发出一个带有特殊Upgrade标头的HTTP请求,通知服务器切换协议(RFC 6455)。在节点中,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 docs on the upgrade eventnode-http-proxy docs