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

5

我在使用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。
谢谢!
2个回答

20

我曾经遇到过同样的问题,花费了一些时间才找出原因。研究后发现,这是因为某些传输方式(例如长轮询)需要进行多次请求以建立最佳连接。在请求之间保持状态,如果不同的连续请求被路由到不同的集群工作进程,则连接将失败。

有一个页面介绍了这个问题:http://socket.io/docs/using-multiple-nodes/,其中引用了一个名为sticky-session的自定义cluster模块来解决这个问题:https://github.com/indutny/sticky-session

我真的不想使用它,因为那基本上就忽略了node.js团队在cluster模块背后的TCP负载均衡所做的全部工作。

由于Web Socket协议本身只需要一个连接,因此我能够通过强制使用websocket作为第一个且仅有的传输方式来解决此问题。我可以这样做是因为我控制客户端和服务器。对于公共网页,这可能不安全,因为您需要担心浏览器兼容性。在我的情况下,客户端是一个移动应用程序。

以下是我在测试页面中放置的JavaScript客户端代码(再次说明,真正的客户端是一个移动应用程序,因此我的网页实际上只是帮助构建和测试的辅助工具):

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

好的回答,应该注意到这当然会阻止你的应用程序与一些客户端数组一起工作,因为它们无法使用websocket传输协议。 - Lee Brindley

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接