Socket.io和Heroku上的多个Dyno Node.js应用程序。 WebSocket在连接build立之前closures

我正在构build一个部署到使用Websockets的Heroku的App。

当我只使用1个dynamic码时,websockets连接正常工作,但当我缩放到大于1时,出现以下错误

POST http://****.herokuapp.com/socket.io/?EIO = 2&transport = polling&t = 1412600135378-1&sid = zQzJJ8oPo5p3yiwIAAAC 400(Bad Request)socket.io-1.0.4.js:2

WebSocket连接到'ws://****.herokuapp.com/socket.io/?EIO = 2&transport = websocket&sid = zQzJJ8oPo5p3yiwIAAAC'失败:WebSocket在连接build立之前closures。 socket.io-1.0.4.js:2

我正在使用Redis适配器来启用多个Web进程

var io = socket.listen(server); var redisAdapter = require('socket.io-redis'); var redis = require('redis'); var pub = redis.createClient(18049, '[URI]', {auth_pass:"[PASS]"}); var sub = redis.createClient(18049, '[URI]', {detect_buffers: true, auth_pass:"[PASS]"} ); io.adapter( redisAdapter({pubClient: pub, subClient: sub}) ); 

这是在本地主机(我正在使用工头,像Heroku一样运行,我正在启动2个Web进程,和Heroku一样)。

在我实现redis适配器之前,我得到了一个web-sockets握手错误,所以适配器有一些影响。 此外,它现在偶尔工作,我假设当套接字匹配相同的networkingdynamic。

我也尝试启用粘滞会话,但它从来没有工作。

 var sticky = require('sticky-session'); sticky(1, server).listen(port, function (err) { if (err) { console.error(err); return process.exit(1); } console.log('Worker listening on %s', port); }); 

我是Heroku的Node.js平台所有者。

WebSockets在多个dynos上开箱即可使用Heroku; socket.io(和其他实时库)使用回退到无状态的进程,如xhr轮询,没有会话亲和力打破。

要扩展socket.io应用程序,请首先按照来自socket.io的所有说明进行操作:

然后,在您的应用上启用会话关联(这是一个免费function):

我花了一段时间,试图使socket.io在多服务器体系结构中工作,首先在Heroku上,然后在Openshift上提出。

使这两个PAAS工作的唯一方法是禁用xhr轮询和设置transports: ['websocket']在客户端和服务器上。

在Openshift上,您必须明确地将服务器的端口设置为8000(对于socket.io客户端初始化的wss-8443,使用* .rhcloud.com服务器,如本文所述: http ://tamas.io / deploy-a-node-jssocket-io-app-to-openshift / 。

投票策略在Heroku上不起作用,因为它不支持粘性会话( https://github.com/Automattic/engine.io/issues/261 ),而在Openshift上,它因为这个问题而失败: https:// github .com / Automattic / engine.io / issues / 279 ,希望尽快解决。

所以,迄今为止唯一的解决scheme是禁用轮询并仅使用websocket传输。

为了做到这一点,用socket.io> 1.0服务器端:

 var app = express(); var server = require('http').createServer(app); var socketio = require('socket.io')(server, { path: '/socket.io-client' }); socketio.set('transports', ['websocket']); 

客户端:

 var ioSocket = io('<your-openshift-app>.rhcloud.com:8000' || '<your-heroku-app>.herokuapp.com', { path: '/socket.io-client' transports: ['websocket'] }) 

希望这会有所帮助。

这可能是你需要运行RedisStore:

 var session = require('express-session'); var RedisStore = require('connect-redis')(session); app.use(session({ store: new RedisStore(options), secret: 'keyboard cat' })); 

每个早期q在这里: Heroku + socket.io广播多个dynos

我知道这不是一个正常的答案,但我试图让WebSockets在Heroku上工作超过一个星期。 经过与客户支持的许多长时间的交谈,我终于尝试了OpenShift。 Heroku WebSockets处于testing阶段,但是OpenShift WebSockets是稳定的。 我在一小时之内就得到了OpenShift的代码。

http://www.openshift.com

我不以任何方式隶属于OpenShift。 我只是一个满意的(不付钱的)客户。

我遇到了很大的问题。 有一些问题同时失败,这是一个巨大的噩梦。 确保你做到以下几点,以在heroku上缩放socket.io:

  1. 如果你使用集群,确保你实施了socketio-sticky-session或类似的东西
  2. 客户端的连接url不应该是https://example.com/socket.io/?EIO=3&transport=polling而是https://example.com/特别是我使用https,因为heroku支持它

  3. 在socket.io中启用cors

  4. 只指定websocket连接

对于你和其他人可能是其中的任何一个。

如果您在设置粘滞会话群集时遇到问题,请参阅我的工作代码

 var http = require('http'); var cluster = require('cluster'); var numCPUs = require('os').cpus().length; var sticky = require('socketio-sticky-session'); var redis = require('socket.io-redis'); var io; if(cluster.isMaster){ console.log('Inside Master'); // create the worker processes for (var i = 0; i < numCPUs ; i++){ cluster.fork(); } } else { // The worker code to be run is written inside // the sticky(). } sticky(function(){ // This code runs inside the workers. // The sticky-session balances connection between workers based on their ip. // So all the requests from the same client would go to the same worker. // If multiple browser windows are opened in the same client, all would be // redirected to the same worker. io = require('socket.io')({transports:'websocket', 'origins' : '*:*'}); var server = http.createServer(function(req,res){ res.end('socket.io'); }) io.listen(server); // The Redis server can also be used to store the socket state //io.adapter(redis({host:'localhost', port:6379})); console.log('Worker: '+cluster.worker.id); // when multiple workers are spawned, the client // cannot connect to the cloudlet. StartConnect(); //this function connects my mongodb, then calls a function with io.on('connection', ..... socket.on('message'...... in relation to the io variable above return server; }).listen(process.env.PORT || 4567, function(){ console.log('Socket.io server is up '); }); 

更多的信息:个人来说,它会从一个不使用websockets的会话中完美地工作(我使用socket.io作为一个统一的游戏,它从编辑器中完美无缺地工作!)。 当通过浏览器连接时,无论是Chrome还是Firefox,都会显示这些握手错误,以及错误503和400。