Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/silverlight/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Node.js http代理删除websocket请求_Javascript_Node.js_Socket.io_Node Http Proxy - Fatal编程技术网

Javascript Node.js http代理删除websocket请求

Javascript Node.js http代理删除websocket请求,javascript,node.js,socket.io,node-http-proxy,Javascript,Node.js,Socket.io,Node Http Proxy,好吧,我花了一个多星期的时间试图弄明白这一点,但没有结果,所以如果有人有线索,你就是英雄。这不是一个容易回答的问题,除非我是个笨蛋 我正在使用node http proxy将粘性会话代理给在不同端口上运行的16个node.js Worker 我使用Socket.IO的Web套接字来处理一系列不同类型的请求,也使用传统的请求 当我将服务器切换到通过节点http代理进行代理时,出现了一个新问题,有时我的Socket.IO会话无法建立连接 实际上,我无法在我的一生中稳定地复制它,打开它的唯一方法是将大

好吧,我花了一个多星期的时间试图弄明白这一点,但没有结果,所以如果有人有线索,你就是英雄。这不是一个容易回答的问题,除非我是个笨蛋

我正在使用node http proxy将粘性会话代理给在不同端口上运行的16个node.js Worker

我使用Socket.IO的Web套接字来处理一系列不同类型的请求,也使用传统的请求

当我将服务器切换到通过节点http代理进行代理时,出现了一个新问题,有时我的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.
});
总结 这是大量的数据,我怀疑是否有人愿意面对它,但我完全被难住了,不知道下一步去哪里检查,下一步去记录,不管怎样,去解决它。我尽我所能想知道问题出在哪里,但毫无结果

更新 好的,我很确定问题出在以下的声明中:


节点http代理是我同意六氰化物。对我来说,通过redis之类的服务或某种消息查询系统让工作人员排队最有意义。工人将通过Redis发布/订阅功能由web节点(代理)排队。工作人员将通过“数据”事件实时回调错误、完成或流式处理数据。也许去图书馆看看。您还可以推出自己的类似库。RabbitMQ是用于类似目的的另一个系统

如果您已经在使用socket.io技术,我会使用socket.io,但您需要为其预期目的使用工具。Redis或MQ系统将是最有意义的,并与WebSocket(socket.io)完美结合,以创建实时、深入的应用程序


aws的弹性负载平衡器支持会话关联(粘性会话),这支持WebSocket。PaaS提供程序()正是这样做的。还有一个为node http proxy提供粘性会话的应用程序,但是我不知道它是否支持WebSocket。

一般来说,我不认为node作为代理服务器不是最常用的选项,我认为node作为node的前端服务器使用,它是一个非常好的组合。下面是一些安装和使用nginx sticky sessions模块的方法

它是一个轻量级的前端服务器,具有类似json的配置,坚固且经过良好测试

如果您想提供静态页面、css,nginx的速度也要快得多。它非常适合配置缓存头、根据域将流量重定向到多个服务器、粘性会话、压缩css和javascript等


<>你也可以考虑一个纯负载均衡的开源解决方案。无论如何,我不认为node是实现这一点的最佳工具,最好只使用它来实现后端,并在它前面放一些类似nginx的东西来处理通常的前端服务器任务。

我自己也在研究类似的东西,目的是生成(和销毁)Node.js动态集群节点

免责声明:我仍然不建议对Node执行此操作;nginx对于您正在寻找的设计体系结构更为稳定,甚至对于HAProxy更为稳定(非常成熟,并且很容易支持粘性会话代理)。正如@tsturzl所指出的,有
卫星
,但鉴于下载量很低,我会小心行事(至少在生产环境中)

这就是说,由于您似乎已经使用Node设置了所有内容,因此重建和重新设计可能比它的价值更大。因此,要安装带有NPM的分支:

  • 使用
    npm卸载节点代理
    和/或
    sudo npm-d卸载节点代理

  • 下载branch.zip并解压缩它

  • 运行
    npm-g安装/path/to/node http代理caronte
  • 在我的例子中,安装链接已断开,因此我必须运行
    sudo npm link http proxy

  • 我已经使用他们的基本代理示例安装并运行了它——无论这是否解决了您的丢弃会话问题,只有您自己知道。

    您使用的是哪个版本的节点?看起来它可能与此相关:-有一个带修复的pull请求,但显然这并不能解决所有问题。v0.10.13-这太旧了吗?老实说,我不太确定它到底在哪里。评论中提到他们在0.10.13中仍然存在问题。你能准确地解释一下你想用它实现什么吗?也许有更好的方法来做事情。很抱歉问一下,为什么你首先需要粘性训练?如果是身份验证,通常可以通过使用redis商店来解决。谢谢,这些都是好主意,我正在研究它们,看看它们是否能够解决问题。有一个问题-你说我需要使用专门用于