使用socket.io / socket.io-redis / rediscloud / node.js在Heroku上使用2个dynos时出错

时间:2014-12-26 22:24:20

标签: node.js sockets heroku socket.io

我有一个在Heroku上运行的node.js / socket.io应用程序。我正在使用带有RedisCloud的socket.io-redis来允许连接到不同dynos的用户进行通信,如here所述。

来自我的app.js:

var express = require('express'),
app = express(),
http = require('http'),
server = http.createServer(app),
io = require('socket.io').listen(server),
redis = require('redis'),
ioredis = require('socket.io-redis'),
url = require('url'),
redisURL = url.parse(process.env.REDISCLOUD_URL),

后来在app.js ......

var sub1 = redis.createClient(redisURL.port, redisURL.hostname, {
    no_ready_check: true,
    return_buffers: true
});
sub1.auth(redisURL.auth.split(":")[1]);
var pub1 = redis.createClient(redisURL.port, redisURL.hostname, {
    no_ready_check: true,
    return_buffers: true
});
pub1.auth(redisURL.auth.split(":")[1]);
var redisOptions = {
    pubClient: pub1,
    subClient: sub1,
    host: redisURL.hostname,
    port: redisURL.port
};
if (io.adapter) {
    io.adapter(ioredis(redisOptions));
    console.log("mylog: io.adapter found");
}

这是一种工作 - 在dynos之间沟通是成功的。

2个dyno发生了三个问题但没有1个dyno:

1)有一个登录提示出现并可靠地使用1 dyno,但是有2个dynos可能会失败 - 可能不会出现,如果确实出现,可能无法正常工作。它是(或应该)由io.sockets.on('connection')事件触发。

2)我在服务器日志中看到很多断开连接。

3)Chrome上的客户端控制台中也存在大量错误,例如:

socket.io.js:5039 WebSocket connection to 'ws://example.mydomain.com/socket.io/?EIO=3&transport=websocket&sid=F8babuJrLI6AYdXZAAAI' failed: Error during WebSocket handshake: Unexpected response code: 503

socket.io.js:2739 POST http://example.mydomain.com/socket.io/?EIO=3&transport=polling&t=1419624845433-63&sid=dkFE9mUbvKfl_fiPAAAJ net::ERR_INCOMPLETE_CHUNKED_ENCODING

socket.io.js:2739 GET http://example.mydomain.com/socket.io/?EIO=3&transport=polling&t=1419624842679-54&sid=Og2ZhJtreOG0wnt8AAAQ 400 (Bad Request)

socket.io.js:3318 WebSocket connection to 'ws://example.mydomain.com/socket.io/?EIO=3&transport=websocket&sid=ITYEPePvxQgs0tcDAAAM' failed: WebSocket is closed before the connection is established.

欢迎任何想法或建议。

1 个答案:

答案 0 :(得分:0)

是的,就像generalhenry所说,问题是Socket.io需要粘性会话(意味着来自给定用户的请求总是转到同一个dyno),而Heroku不支持它。

(它适用于1 dyno,因为只有1 dyno然后所有请求都会转到它。)

https://github.com/Automattic/engine.io/issues/261有更多的好信息,显然网络套接字并不真正需要粘性会话,但长轮询确实如此。它还提到了一些潜在的解决方法:

  • 回滚到socket.io版本0.9.17,首先尝试websockets
  • 只使用SSL连接,这使得websockets更可靠(因为ISP和公司代理以及其他东西不能轻易修改连接。)

结合这两者,你可能会得到最好的结果。

  • 您还可以启动自己的负载均衡器,增加粘性会话支持,但到那时,您正在与Heroku作战,并且可能会在不同的主机上做得更好。

RE:关于Node.js群集模块的另一个问题:这在这里确实没有用。它用于在单个服务器/ dyno上使用所有可用的CPU核心,