Node.JS、Socket.IO 和集群中的 WebSocket 握手不起作用

Posted

技术标签:

【中文标题】Node.JS、Socket.IO 和集群中的 WebSocket 握手不起作用【英文标题】:WebSocket handshake in Node.JS, Socket.IO and Clusters not working 【发布时间】:2014-12-10 01:12:55 【问题描述】:

我在使用 Node.js、socket.io 和 node.js 集群对我的应用程序进行集群时遇到问题。

我使用 socket.io-redis 为所有工作人员共享信息,但无法正常工作。

我的代码:

var cluster   = require('cluster');
var numCPUs = require('os').cpus().length;

if (cluster.isMaster)    
  // Fork workers.
  for (var i = 0; i < numCPUs; i++)       
    cluster.fork();
  

  cluster.on('exit', function(worker, code, signal) 
    console.log('worker ' + worker.process.pid + ' died');
  );
 else 

    ...

         var express   = require("express");
         //Server
         var server = express();
         //Socket.io
         var http  = require('http').Server(server);
         var io    = require('socket.io')(http);
         var redis_io = require('socket.io-redis'); 
         var redis = require("redis");

         io.adapter(redis_io(host: "127.0.0.1", port: 6379 )); 

    ...

在客户端,我在握手中遇到错误,例如 400 错误或 WebSocket 在建立连接之前已关闭。

我能做些什么来解决这个问题?

我正在使用最新版本的 node.js 和 socket.io

谢谢!

【问题讨论】:

【参考方案1】:

我遇到了同样的问题,我花了一段时间才弄清楚。一些研究解释说,这是因为一些传输,如长轮询,需要发出多个请求才能建立最佳连接。请求之间存在状态,因此如果不同的连续请求被路由到不同的集群工作人员,则连接失败。

在http://socket.io/docs/using-multiple-nodes/ 有一个关于它的页面,它引用了一个名为sticky-session 的自定义cluster 模块,它可以解决这个问题:https://github.com/indutny/sticky-session

我真的不想使用它,因为它基本上忽略了 node.js 团队一直在集群模块背后的 TCP 负载平衡方面投入的所有工作。

由于 Web Socket 协议本身只需要一个连接,我可以通过强制 websocket 成为第一个也是唯一的传输来解决这个问题。我可以这样做,因为我控制着客户端和服务器。对于公共网页,这对您来说可能不安全,因为您必须担心浏览器的兼容性。在我的例子中,客户端是一个移动应用程序。

这是我放入测试页面的 javascript 客户端代码(同样,真正的客户端是移动应用程序,所以我的网页实际上只是帮助构建和测试):

var socket = io('http://localhost:8080/', 
  transports: [ 'websocket' ]
);

【讨论】:

好的答案,应该注意的是,这当然会阻止您的应用程序与一组客户端一起工作,这些客户端由于任何原因都无法使用 websocket 传输协议【参考方案2】:

您必须使用 sticky-session 来避免客户端从初始握手连接到不同的服务器。参考这个https://github.com/elad/node-cluster-socket.io

【讨论】:

以上是关于Node.JS、Socket.IO 和集群中的 WebSocket 握手不起作用的主要内容,如果未能解决你的问题,请参考以下文章

Node.js Socket.IO 聊天应用集群服务器

在 Heroku 上使用集群和 socket.io-redis 扩展 node.js socket.io@1.*.*

我在集群 node.js/socket.io/redis pub/sub 应用程序中收到重复消息

使用集群将 Socket.IO 扩展到多个 Node.js 进程时的一些问题

Node.js、多线程和 Socket.io

Phaser.js 中的 Node.js 和 Socket.io 未连接 socket.io/?EIO=3&transport=polling