我使用node.js
,express
和socket.io
制作了一个基本聊天应用。它与socket.io的tutorial chat app没有什么不同,它只是在连接的客户端之间发出事件。当我在服务器上的端口3001上运行它时,它工作正常。
然后我使用node-http-proxy
创建了一个代理服务器应用程序,该应用程序侦听端口80,并根据请求的URL将流量重定向到我在不同端口上运行的各种独立节点应用程序。非常直截了当。但有些事情正在破裂。每当有人断开连接时,每个插座都会断开并重新连接。这对我的聊天应用程序来说很糟糕,因为它有基于连接的事件。客户端控制台都显示:
WebSocket连接到' ws:// [某些套接字信息] '失败:在收到握手响应之前关闭连接
我认为这是我的代码的重要部分。
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's site上阅读的内容,我可能需要使用一些东西通过我的代理服务器来承载套接字流量。我认为node-http-proxy通过their docs中的{ws: true}
选项为我做了这个,但显然它并没有像我想象的那样工作。 socket.io提到了三个不同的东西:
sticky session
基于cluster
模块socket.io-redis
,允许单独的socket.io实例相互通信socket.io-emitter
,允许socket.io与nonsocket.io进程通信我完全不知道这意味着什么或做了什么。我不小心在这里编写了高于我的技能水平的编码,我不知道这些工具中的哪一个会解决我的问题(如果有的话),甚至我的问题的原因是什么。
强制道歉:我是node.js的新手,所以请原谅我。
也是强制性的:我知道像nginx这样的其他应用程序可以解决我的很多问题,但我的目标是在学习新工具之前学习并理解如何使用这套工具。而且,我使用的应用程序越少越好。
答案 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 event和node-http-proxy docs。