在Heroku Node.js应用程序上的Socket.io和多个Dyno.在建立连接之前关闭WebSocket

Jac*_*ild 24 heroku websocket redis node.js socket.io

我正在构建一个部署到Heroku的App,它使用Websockets.

当我只使用1个dyno时,websockets连接正常工作,但当我缩放到> 1时,我得到以下错误

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

WebSocket连接到'ws://****.herokuapp.com/socket.io/?EIO = 2&transport = websocket&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}) );
Run Code Online (Sandbox Code Playgroud)

这正在localhost(我正在使用工头运行,正如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);
});
Run Code Online (Sandbox Code Playgroud)

hun*_*tis 19

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

WebSockets可以在Heroku开箱即用,可以在多个动态游戏中使用; socket.io(和其他实时库)使用回退到无状态进程,如xhr轮询,没有会话亲和性.

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

然后,在您的应用上启用会话亲缘关系(这是一项免费功能):

  • 嘿,猎人.你有没有关于每个dyno可以处理的并发socket.io连接数的信息?(棒球场很好).谢谢. (2认同)
  • 这适合我!我做了@hunterloftis的建议,我正在使用[socket.io-redis](https://github.com/socketio/socket.io-redis)和heroku中的会话亲和力,一切都很棒:) (2认同)

小智 6

我花了一段时间试图让 socket.io 在多服务器架构中工作,首先在 Heroku 上,然后在许多人建议的 Openshift 上。

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

在 Openshift 上,您必须明确地将服务器的端口设置为 8000(对于 ws – 8443 对于 wss on socket.io 客户端初始化,使用 *.rhcloud.com 服务器,如本文所述:http ://tamas.io /deploying-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,这有望很快得到修复。

因此,到目前为止我找到的唯一解决方案是禁用轮询并仅使用 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']);
Run Code Online (Sandbox Code Playgroud)

客户端:

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

希望这会有所帮助。


aug*_*uag 1

可能您需要运行 RedisStore:

var session = require('express-session');
var RedisStore = require('connect-redis')(session);

app.use(session({
    store: new RedisStore(options),
    secret: 'keyboard cat'
}));
Run Code Online (Sandbox Code Playgroud)

根据之前的问题:Heroku + socket.io 广播上的多个测功机