我正在构建一个使用Websockets部署到Heroku的应用程序。
当我只使用1个dyno时,websockets连接正常工作,但当我缩放到> 1时,我得到以下错误
POST HTTP://****.herokuapp.com/socket.io/ EIO = 2及运输=轮询& T公司= 1412600135378-1&安培; SID = zQzJJ8oPo5p3yiwIAAAC 400(错误请求)socket.io-1.0.4.js:2
WebSocket连接到 'WS://****.herokuapp.com/socket.io/ EIO = 2及运输=网页套接字&安培; SID = zQzJJ8oPo5p3yiwIAAAC? 失败:在建立连接之前关闭WebSocket。 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}) );
这正在使用localhost(我正在使用foreman运行,正如Heroku所做的那样,我正在启动2个Web进程,与Heroku相同)。
在我实现redis适配器之前,我遇到了Web套接字握手错误,因此适配器产生了一些影响。它现在偶尔也在工作,我假设当套接字匹配相同的web dyno时。
我也试图启用粘性会话,但它永远不会有效。
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);
});
答案 0 :(得分:19)
我是Heroku的Node.js平台所有者。
WebSockets在Heroku上可以在多个动态游戏中开箱即用; socket.io(和其他实时库)使用回退到无状态进程,如xhr轮询,没有会话亲和力。
要扩展socket.io应用程序,请先按照socket.io中的所有说明进行操作:
然后,在您的应用上启用会话亲和力(这是一项免费功能):
答案 1 :(得分:4)
我花了一些时间尝试使socket.io在多服务器架构中工作,首先在Heroku上工作,然后在许多人建议的Openshift上工作。
使其适用于两种PAAS的唯一方法是禁用xhr-polling并在客户端和服务器上设置transports: ['websocket']
。
在Openshift上,你必须使用* .rhcloud.com服务器显式地将服务器的端口设置为8000(对于ws - 8443,对于socket.io客户端初始化的wss,如本文所述:{{3} }。
轮询策略在Heroku上不起作用,因为它不支持粘性会话(http://tamas.io/deploying-a-node-jssocket-io-app-to-openshift/),而在Openshift上它因为这个问题而失败:https://github.com/Automattic/engine.io/issues/261,希望很快得到解决。< / p>
因此,到目前为止我找到的唯一解决方案是禁用轮询并仅使用websocket传输。
为了做到这一点,请使用socket.io&gt; 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']
})
希望这会有所帮助。
答案 2 :(得分:1)
您可能需要运行RedisStore:
var session = require('express-session');
var RedisStore = require('connect-redis')(session);
app.use(session({
store: new RedisStore(options),
secret: 'keyboard cat'
}));
答案 3 :(得分:1)
我知道这不是一个正常的答案,但我已经尝试让WebSockets在Heroku上工作超过一周。经过与客户支持的长时间对话后,我终于尝试了OpenShift。 Heroku WebSockets处于测试阶段,但OpenShift WebSockets稳定。我在一小时内完成了OpenShift的代码。
我不以任何方式与OpenShift有任何关系。我只是一个满意的(非付费)客户。
答案 4 :(得分:0)
我遇到了很多问题。有许多问题未能同时成为一场巨大的噩梦。请确保执行以下操作以在heroku上扩展socket.io:
客户端的连接网址不应该是https://example.com/socket.io/?EIO=3&transport=polling
,而是https://example.com/
,尤其是我使用https,因为heroku支持它
对于你和其他人来说,它可以是其中任何一个。
如果您在设置粘性会话群集时遇到问题,请参阅我的工作代码
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.