Node.js http-proxy丢弃websocket请求 [英] Node.js http-proxy drops websocket requests

查看:116
本文介绍了Node.js http-proxy丢弃websocket请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好吧,我花了一个多星期试图弄清楚这一点无济于事,所以如果有人有线索,你就是英雄。这不是一个容易回答的问题,除非我是个笨蛋。

Okay, I've spent over a week trying to figure this out to no avail, so if anyone has a clue, you are a hero. This isn't going to be an easy question to answer, unless I am being a dunce.

我使用node-http-proxy代理在不同端口上运行的16个node.js工作人员的粘性会话。

I am using node-http-proxy to proxy sticky sessions to 16 node.js workers running on different ports.

我使用Socket.IO的Web套接字处理一堆不同类型的请求,并使用传统请求。

I use Socket.IO's Web Sockets to handle a bunch of different types of requests, and use traditional requests as well.

当我将服务器切换到代理时通过node-http-proxy,一个新的问题随之而来,有时,我的Socket.IO会话无法建立连接。

When I switched my server over to proxying via node-http-proxy, a new problem crept up in that sometimes, my Socket.IO session cannot establish a connection.

我实际上无法稳定地重现它我的生活,唯一的方法是将多个客户端的大量流量投入服务器。

I literally can't stably reproduce it for the life of me, with the only way to turn it on being to throw a lot of traffic from multiple clients to the server.

如果我重新加载用户的浏览器,它然后有时可以重新连接,有时不会重新连接。

If I reload the user's browser, it can then sometimes re-connect, and sometimes not.

我必须将粘性会话代理为我的应用程序基于每个工作人员进行身份验证,因此它根据其Connect.SID cookie路由请求(我正在使用connect / express)。

I have to proxy sticky sessions as my app authenticates on a per-worker basis, and so it routes a request based on its Connect.SID cookie (I am using connect/express).

这个是我的proxy.js文件,它在节点中运行并路由到每个工作人员:

This is my proxy.js file that runs in node and routes to each of the workers:

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

});



客户端/现象



插座像这样连接:

Client Side / The Phenomena

Socket connects like so:

var socket = io.connect('http://whatever:8888');

登录后大约10秒钟后,我在这个监听器上收到此错误,帮助很多。

After about 10 seconds on logging on, I get this error back on this listener, which doesn't help much.

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请求永远不会回来 - 它只是挂起待定,甚至错误回来后,它看起来像一个超时错误。服务器永远不会响应。

The Socket.IO GET request that the browser sends never comes back - it just hangs in pending, even after the error comes back, so it looks like a timeout error. The server never responds.

这是工作人员收到套接字请求的方式。很简单。所有工作人员都有相同的代码,所以你认为其中一个人会得到请求并承认它...

This is how a worker receives a socket request. Pretty simple. All workers have the same code, so you think one of them would get the request and acknowledge it...

app.sio.socketio.sockets.on('connection', function (socket) {
  // works... some of the time! all of my workers run this
  // exact same process.
});



摘要



这是很多数据,我怀疑是否有人愿意面对它,但我完全难倒,不知道接下来要检查的地方,接下来记录,无论如何,要解决它。我已经尝试了我所知道的一切,看看问题是什么,但无济于事。

Summary

That's a lot of data, and I doubt anyone is willing to confront it, but i'm totally stumped, don't know where to check next, log next, whatever, to solve it. I've tried everything I know to see what the problem is, to no avail.

好的,我很确定问题出现在 node-http-proxy github主页的声明中:

Okay, I am fairly certain that the problem is in this statement on the node-http-proxy github homepage:


node-http-proxy与< = 0.8.x兼容,如果你正在寻找> =
0.10兼容版本请检查caronte

node-http-proxy is <= 0.8.x compatible, if you're looking for a >= 0.10 compatible version please check caronte

我正在运行Node.js v0.10.13,而这些现象正如一些人在github问题上所评论的那样主题:它只是随机丢弃websocket连接。

I am running Node.js v0.10.13, and the phenomena is exactly as some have commented in github issues on this subject: it just drops websocket connections randomly.

我试图实现caronte,'更新'的分叉,但它根本没有记录,我试过我的最难将他们的文档拼凑在一个可行的解决方案中,但我不能让它转发websockets,我的Socket.IO降级为轮询。

I've tried to implement caronte, the 'newer' fork, but it is not at all documented and I have tried my hardest to piece together their docs in a workable solution, but I can't get it forwarding websockets, my Socket.IO downgrades to polling.

还有其他任何想法吗?如何实现和实施? node-http-proxy昨天有8200次下载!当然有人正在使用今年的Node构建和代理websockets ....

Are there any other ideas on how to get this implemented and working? node-http-proxy has 8200 downloads yesterday! Sure someone is using a Node build from this year and proxying websockets....

我想完成代理多个node.js工作者的代理服务器(最好是Node),并根据浏览器cookie通过粘性会话路由请求。此代理需要稳定支持传统请求以及Web套接字。

I want to accomplish a proxy server (preferrably Node) that proxies to multiple node.js workers, and which routes the requests via sticky sessions based on a browser cookie. This proxy would need to stably support traditional requests as well as web sockets.

I不介意通过群集节点工作者完成上述操作,如果可行的话。我唯一真正的要求是根据请求标题中的cookie维护粘性会话。

I don't mind accomplishing the above via clustered node workers, if that works. My only real requirement is maintaining sticky sessions based on a cookie in the request header.

如果有更好的方法来完成上述操作而不是我正在尝试的,我就是一切都是为了它。

If there is a better way to accomplish the above than what I am trying, I am all for it.

推荐答案

一般来说,我认为节点不是最常用的选项作为代理服务器,I,一次性使用< a href =http://nginx.org/ =nofollow noreferrer> nginx 作为节点的前端服务器,它是一个非常好的组合。以下是一些说明安装并使用nginx粘性会话模块。

In general I don't think node is not the most used option as a proxy server, I, for one use nginx as a frontend server for node and it's a really great combination. Here are some instructions to install and use the nginx sticky sessions module.

这是一个轻量级的前端服务器,配置类似json,稳定且经过良好测试。

It's a lightweight frontend server with json like configuration, solid and very well tested.

nginx也要快得多。这是配置缓存标头,根据域,粘性会话,压缩css和javascript等将流量重定向到多个服务器的理想选择。

nginx is also a lot faster if you want to serve static pages, css. It's ideal to configure your caching headers, redirect traffic to multiple servers depending on domain, sticky sessions, compress css and javascript, etc.

您还可以考虑纯负载平衡开源解决方案,如 HAProxy 。在任何情况下,我都不相信node是最好的工具,最好只使用它来实现你的后端,并在它前面添加类似nginx的东西来处理通常的前端服务器任务。

You could also consider a pure load balancing open source solution like HAProxy. In any case I don't believe node is the best tool for this, it's better to use it to implement your backend only and put something like nginx in front of it to handle the usual frontend server tasks.

这篇关于Node.js http-proxy丢弃websocket请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆