我用node.js
,express
和socket.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这样的其他应用程序可以解决我的很多问题,但我的目标是在我开始使用新的工具之前学习和理解如何使用这套工具。而且,我使用的应用程序越少越好。
我认为您的直觉是正确的,需要“通过”代理服务器的套接字流量。为了建立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文档。