使用socket.io / socket.io-redis / rediscloud / node.js在Heroku上使用2个dynos的错误 [英] Errors going to 2 dynos on Heroku with socket.io / socket.io-redis / rediscloud / node.js

查看:217
本文介绍了使用socket.io / socket.io-redis / rediscloud / node.js在Heroku上使用2个dynos的错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



从我的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 ...

$ $ p $ 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,$ b $ port:redisURL.port
};
if(io.adapter){
io.adapter(ioredis(redisOptions));
console.log(mylog:io.adapter found);
}

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



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

1)有一个登录提示符它出现并可靠地使用1台动态测试仪,但是有2个动态测试仪可能会出现问题 - 可能不会出现,如果出现则可能无法正常工作。这是(或应该)由io.sockets.on('连接')事件触发。



2)我看到服务器中有很多断开连接登录。



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

  socket.io.js:5039 WebSocket连接到'ws://example.mydomain.com/socket.io/?EIO = 3& transport = websocket& sid = F8babuJrLI6AYdXZAAAI'失败:WebSocket握手期间出错:意外的响应代码: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连接到'ws://example.mydomain.com/socket.io/?EIO = 3& transport = websocket& sid = ITYEPePvxQgs0tcDAAAM'失败:WebSocket在建立连接之前关闭。

任何想法或建议都会受到欢迎。

$ b

(它可以与1个动态码一起工作,因为当只有1个时,所有请求都会到达它。)



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


  • 回滚到socket.io版本0.9.17,它首先尝试websocket li>
  • 只有使用SSL连接才能使websockets更加可靠(因为ISP和公司代理以及无法轻松修改连接的服务)。



您可能会将这两者结合起来获得最佳效果。


  • 您也可以旋转起来你自己的负载均衡器增加了对会话的支持,但是到那时为止,你正在与Heroku战斗,而且在不同的主机上可能会更好。


:关于Node.js集群模块的其他问题:这里没有什么帮助。它用于在单个服务器/测试仪上使用所有可用的CPU核心,

I have a node.js / socket.io app running on Heroku. I am using socket.io-redis with RedisCloud to allow users who connect to different dynos to communicate, as described here.

From my 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),

And later in 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");
}

It is kind of working -- communication is succeeding between dynos.

Three issues that happen with 2 dynos but not with 1 dyno:

1) There is a login prompt which comes up and works reliably with 1 dyno but is hit-and-miss with 2 dynos -- may not come up and may not work if it does come up. It is (or should be) triggered by the io.sockets.on('connection') event.

2) I'm seeing a lot of disconnects in the server log.

3) Also lots of errors in the client console on Chrome, for example:

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.

Any thoughts or suggestions would be welcome.

解决方案

Yes, like generalhenry said, the issue is that Socket.io requires sticky sessions (meaning that requests from a given user always go to the same dyno), and Heroku doesn't support that.

(It works with 1 dyno because when there's only 1 then all requests go to it.)

https://github.com/Automattic/engine.io/issues/261 has a lot more good info, apparently web sockets don't really require sticky sessions, but long-polling does. It also mentions a couple of potential work-arounds:

  • Roll back to socket.io version 0.9.17, which tries websockets first
  • Only use SSL connections which, makes websockets more reliable (because ISP's and corporate proxies and whatnot can't tinker with the connection as easily.)

You might get the best results from combining both of those.

  • You could also spin up your own load balancer that adds sticky session support, but by that point, you're fighting against Heroku and might be better off on a different host.

RE: your other question about the Node.js cluster module: it wouldn't really help here. It's for using up all of the available CPU cores on a single server/dyno,

这篇关于使用socket.io / socket.io-redis / rediscloud / node.js在Heroku上使用2个dynos的错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆