【问题标题】:Socket.io 'Handshake' failing with cluster and sticky-sessionSocket.io 'Handshake' 因集群和粘性会话而失败
【发布时间】:2015-02-13 21:15:40
【问题描述】:

即使是一个简单的示例,我也无法让sticky-sessions socket.io 模块正常工作。按照自述文件 (https://github.com/indutny/sticky-session) 中给出的最小示例,我只是想让这个示例正常工作:

var cluster = require('cluster');
var sticky = require('sticky-session');
var http   = require('http');

if (cluster.isMaster) {
  for (var i = 0; i < 4; i++) {
    cluster.fork();
  }

  Object.keys(cluster.workers).forEach(function(id) {
    console.log("Worker running with ID : " + 
      cluster.workers[id].process.pid);
  });
}

if (cluster.isWorker) {
  var anotherServer = http.createServer(function(req, res) {
    res.end('hello world!');
  });
  anotherServer.listen(3000);
  console.log('http server on 3000');
}

sticky(function() {
  var io = require('socket.io')();

  var server = http.createServer(function(req, res) {
    res.end('socket.io');
  });

  io.listen(server);

  io.on('connection', function onConnect(socket) {
    console.log('someone connected.');

    socket.on('sync', sync);
    socket.on('send', send);

    function sync(id) {
      socket.join(id);
      console.log('someone joined ' + id);
    }

    function send(id, msg) {
      io.sockets.in(id).emit(msg);
      console.log('someone sent ' + msg + ' to ' + id);
    }
  });

  return server;
}).listen(3001, function() {
  console.log('socket.io server on 3001')
});

还有一个简单的客户:

var socket = require('socket.io-client')('http://localhost:3001');

socket.on('connect', function() { 
  console.log('connected')
  socket.emit('sync', 'secret') 
});

工人启动良好。 http 服务器工作正常。但是当客户端连接时,控制台会记录“有人连接”,仅此而已。客户端从不触发 on connect 事件,所以我认为升级/握手失败或其他什么。如果有人能发现我做错了什么,那将有很大帮助。

谢谢!

【问题讨论】:

  • 曾经解决过这个问题吗?我只是遇到客户端不断重新连接的问题
  • 基本上不维护粘性会话。我不想使用redis,因为我希望一切都简单,但最后我不得不这样做。 redis 适配器非常易于使用,您无需进行任何配置。只需安装 redis 并将所有内容连接起来。为了让它在集群上工作,我必须做最后一件事:我必须在客户端和服务器上指定传输:web 套接字。 WS 必须是第一个(ws,然后是轮询)或唯一的选择。完成这两件事后,一切都完美无缺。如果需要,我可以用示例更新我的答案。
  • 感谢您的回复,是的,这将非常有帮助:)

标签: node.js session websocket socket.io cluster-computing


【解决方案1】:

@jordyyy :我在谷歌搜索后遇到了同样的问题,我有很好的答案。 Socket.Io 握手任务在多个请求中完成,当您在粘性会话上运行时,这意味着您正在根据您的核心使用多个进程。

因此握手请求将分布在不同的不同进程上,它们无法交谈。(不是 IPC)(它们是子进程)并且大部分时间连接将失败/丢失。(连接断开事件经常发生)

那么解决方案是什么?解决办法是socketio-sticky-session

Socketio-sticky-session,基于 IP 管理连接。因此,当您请求任何客户端时,它将维护与进程/工作人员相关的 IP 地址。因此,进一步的请求将转发给相同的进程/工作人员,并且您的连接会正确稳定。

当你将使用 redies 适配器时,你实际上可以维护套接字 连接数据 b/w 所有进程/工作人员。

更多信息 https://github.com/elad/node-cluster-socket.io (如果您的服务器支持 IPv6,则需要对 worker_index 方法进行一些补丁)

只是知识字节。 :) :)

还有一点,你不需要 fork 进程。它将通过粘性会话完成。

【讨论】:

  • 感谢您的意见。我很乐意接受建议,但问题是关于特定模块的,我真的不认为使用另一个模块是一个好的答案
  • @jordyyy : 欢迎您 :) 当您打开此模块库时。它只是一个文件脚本。和你写的一样,除了连接处理:)
【解决方案2】:

这是超级旧的,当我需要它时并没有真正回答,但我的解决方案是删除这个坏模块和任何其他超级混乱的模块,只使用带有 redis 适配器的 pub/sub。唯一的其他步骤是强制传输到 websockets,如果这让任何人感到困扰,那么请使用其他东西。就我的目的而言,我的解决方案简单易读,没有与“典型”socket.io api 混淆,最重要的是它运行得非常好。

【讨论】:

  • 将传输限制为仅 websocket 对我来说效果很好。
  • 您能否为我们这些想要尝试您的解决方案的人添加代码?
猜你喜欢
  • 2014-12-19
  • 1970-01-01
  • 2020-04-03
  • 2018-12-20
  • 2012-11-21
  • 1970-01-01
  • 1970-01-01
  • 2014-07-16
  • 2017-11-29
相关资源
最近更新 更多