使用Socket.io和Redis在Heroku上运行Node.js应用程序

4
我正在尝试使用Node.js和Socket.io与Redis将应用程序部署到Heroku。我已经设置了Socket.io使用XHR长轮询,如Heroku所指定的,如果只有一个dyno,它可以完美地工作,但是当我扩展它以使用多个dyno时,它就无法正常工作。
最初我在Socket.io中使用MemoryStore,当我使用“heroku ps:scale web = 2”进行扩展时,它开始间歇性地工作,并在客户端中显示此错误:
未捕获的类型错误:对象#<Transport>的属性“open”不是函数
我在Socket.io文档中发现:“如果要扩展到多个进程和/或多个服务器,可以使用我们的RedisStore,它使用Redis NoSQL数据库作为中间人”。
因此,我创建了一个RedisStore:
var newRedisStore = new RedisStore({
  redisPub : pub,
  redisSub : sub,
  redisClient : client
});

并配置了 Socket.io 来使用它:

//set up Web Socket Server
io.configure(function () { 
  io.set("transports", ["xhr-polling"]);
  io.set("polling duration", 10);
  io.set('store', newRedisStore);
});

一切在本地以及 Heroku 中一个 Web Dyno 上运行都完美无误。但是,一旦将其扩展到超过一个进程,它开始间歇性失效,尽管现在不再出现错误。因此,我不确定接下来该怎么做。
以下是我在使用两个进程的 Heroku 上得到的日志:
2012年6月16日15:36:12+00:00应用程序[web.2]:调试:设置轮询超时
2012年6月16日15:36:12+00:00应用程序[web.2]:调试:清除轮询超时
2012年6月16日15:36:12+00:00应用程序[web.2]:调试:xhr-polling写入
7:::1 + 0 2012年6月16日15:36:12+00:00应用程序[web.2]:警告:客户端未握手,客户端应重新连接
2012年6月16日15:36:12+00:00应用程序[web.2]:调试:为客户端15718037491002932534设置关闭超时
2012年6月16日15:36:12+00:00应用程序[web.2]:调试:清除客户端15718037491002932534的关闭超时
2012年6月16日15:36:12+00:00应用程序[web.2]:信息:传输结束(错误)
2012年6月16日15:36:12+00:00应用程序[web.2]:调试:丢弃传输
2个回答

1

你尝试过使用Node的Cluster模块吗? http://nodejs.org/api/cluster.html

比如:

var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
  // Fork workers.
  for (var i = 0; i < numCPUs; i++) {
    cluster.fork();
  }

  cluster.on('death', function(worker) {
    console.log('worker ' + worker.pid + ' died');
  });
} else {
  // Worker processes have a http server.
  http.Server(function(req, res) {
    res.writeHead(200);
    res.end("hello world\n");
  }).listen(8000);
}

或者:

var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
  // Fork workers.
  for (var i = 0; i < numCPUs; i++) {
    cluster.fork();
  }
} else {
  var sio = require('socket.io')
  , RedisStore = sio.RedisStore
  , io = sio.listen(8080, options);

  // Somehow pass this information to the workers
  io.set('store', new RedisStore);

  // Do the work here
  io.sockets.on('connection', function (socket) {
    socket.on('chat', function (data) {
      socket.broadcast.emit('chat', data);
    })
  });
}

就像你可以在这里看到的那样。


谢谢。我感觉这是朝着正确的方向前进,但似乎无法让它工作。当我使用集群时,Socket.io在发出错误时会出现问题。 - tomgersic
尝试增加超时时间,然后让我知道。另外,你能否发布你的代码,这样我就可以分析它,使用pastebin.com或类似的网站。 - Eugene Hauptmann

0

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