好吧,我花了一个多星期的时间试图弄清楚这一点无济于事,所以如果有人有线索,你就是英雄.这不是一个容易回答的问题,除非我是个笨蛋.
我正在使用node-http-proxy来代理在不同端口上运行的16个node.js工作者的粘性会话.
我使用Socket.IO的Web套接字来处理一堆不同类型的请求,并使用传统请求.
当我通过node-http-proxy将服务器切换到代理时,一个新的问题随之而来,我的Socket.IO会话有时无法建立连接.
我确实无法在我的生活中稳定地重现它,唯一的方法是将其从多个客户端投入大量流量到服务器.
如果我重新加载用户的浏览器,它有时可能会重新连接,有时不会重新连接.
我必须代理粘性会话,因为我的应用程序基于每个工作人员进行身份验证,因此它根据其Connect.SID cookie(我正在使用connect/express)路由请求.
这是我的proxy.js文件,它在节点中运行并路由到每个worker:
var http = require('http'); var httpProxy = require('http-proxy'); // What ports the proxy is routing to. var data = { proxyPort: 8888, currentPort: 8850, portStart: 8850, portEnd: 8865, }; // Just gives the next port number. nextPort = function() { var next = data.currentPort++; next = (next > data.portEnd) ? data.portStart : next; data.currentPort = next; return data.currentPort; }; // A hash of Connect.SIDs for sticky sessions. data.routes = {} var svr = httpProxy.createServer(function (req, res, proxy) { var port = false; // parseCookies is just a little function // that... parses cookies. var cookies = parseCookies(req); // If there is an SID passed from the browser. if (cookies['connect.sid'] !== undefined) { var ip = req.connection.remoteAddress; if (data.routes[cookies['connect.sid']] !== undefined) { // If there is already a route assigned to this SID, // make that route's port the assigned port. port = data.routes[cookies['connect.sid']].port; } else { // If there isn't a route for this SID, // create the route object and log its // assigned port. port = data.currentPort; data.routes[cookies['connect.sid']] = { port: port, } nextPort(); } } else { // Otherwise assign a random port, it will/ // pick up a connect SID on the next go. // This doesn't really happen. port = nextPort(); } // Now that we have the chosen port, // proxy the request. proxy.proxyRequest(req, res, { host: '127.0.0.1', port: port }); }).listen(data.proxyPort); // Now we handle WebSocket requests. // Basically, I feed off of the above route // logic and try to route my WebSocket to the // same server regular requests are going to. svr.on('upgrade', function (req, socket, head) { var cookies = parseCookies(req); var port = false; // Make sure there is a Connect.SID, if (cookies['connect.sid'] != undefined) { // Make sure there is a route... if (data.routes[cookies['connect.sid']] !== undefined) { // Assign the appropriate port. port = data.routes[cookies['connect.sid']].port; } else { // this has never, ever happened, i've been logging it. } } else { // this has never, ever happened, i've been logging it. }; if (port === false) { // this has never happened... }; // So now route the WebSocket to the same port // as the regular requests are getting. svr.proxy.proxyWebSocketRequest(req, socket, head, { host: 'localhost', port: port }); });
套接字连接如下:
var socket = io.connect('http://whatever:8888');
登录后大约10秒钟后,我在此侦听器上收到此错误,这没有多大帮助.
socket.on('error', function (data) { // this is what gets triggered. -> // Firefox can't establish a connection to the server at ws://whatever:8888/socket.io/1/websocket/Nnx08nYaZkLY2N479KX0. });
浏览器发送的Socket.IO GET请求永远不会回来 - 它只是在挂起时挂起,即使在错误返回后,它看起来像是超时错误.服务器永远不会响应.
这是工作者接收套接字请求的方式.很简单.所有工人都有相同的代码,所以你认为他们中的一个会收到请求并承认它...
app.sio.socketio.sockets.on('connection', function (socket) { // works... some of the time! all of my workers run this // exact same process. });
这是很多数据,我怀疑是否有人愿意面对它,但我完全难过,不知道接下来要检查的地方,接下来记录,无论如何,要解决它.我已经尝试了我所知道的一切,看看问题是什么,但无济于事.
好的,我很确定问题出在node-http-proxy github主页上的这个语句中:
node-http-proxy与<= 0.8.x兼容,如果您正在寻找> = 0.10兼容版本请检查caronte
我正在运行Node.js v0.10.13,这个现象正如一些人在github问题上评论过这个主题:它只是随机丢弃websocket连接.
我试图实现caronte,'更新'的分支,但它根本没有记录,我已经尽力将他们的文档拼凑在一个可行的解决方案中,但我无法让它转发websockets,我的Socket. IO降级为民意调查.
关于如何实现和运作,还有其他想法吗?node-http-proxy昨天有8200次下载!当然有人正在使用今年的Node构建和代理websockets ....
我想完成代理多个node.js工作的代理服务器(最好是Node),并根据浏览器cookie通过粘性会话路由请求.此代理需要稳定地支持传统请求以及Web套接字.
我不介意通过群集节点工作者完成上述工作,如果可行的话.我唯一真正的要求是根据请求标头中的cookie维护粘性会话.
如果有一个更好的方法来实现上述目标而不是我正在尝试,我就是全力以赴.