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 握手不起作用的主要内容,如果未能解决你的问题,请参考以下文章
在 Heroku 上使用集群和 socket.io-redis 扩展 node.js socket.io@1.*.*
我在集群 node.js/socket.io/redis pub/sub 应用程序中收到重复消息
使用集群将 Socket.IO 扩展到多个 Node.js 进程时的一些问题
Phaser.js 中的 Node.js 和 Socket.io 未连接 socket.io/?EIO=3&transport=polling