Ошибки, идущие на 2 динамика на Heroku с socket.io/socket.io-redis/rediscloud/node.js

У меня есть приложение node.js/socket.io, работающее на Heroku. Я использую socket.io-redis с RedisCloud, чтобы позволить пользователям, которые подключаются к разным динамикам для общения, как описано здесь.

Из моего 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");
}

Это своего рода работа - общение преуспевает между динамиками.

Три проблемы, которые происходят с двумя динамиками, но не с 1 dyno:

1) Появляется приглашение для входа в систему, которое надежно работает с 1 динамометрическим процессором, но с двумя динозаводами, и может быть неработающим, если оно появляется. Это (или должно быть) вызвано событием 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

Да, как сказал генералэнни, проблема в том, что Socket.io требует липких сеансов (что означает, что запросы от данного пользователя всегда идут на один и тот же динамик), и Heroku не поддерживает это.

(Он работает с 1 dyno, потому что, когда только 1, все запросы идут на него.)

https://github.com/Automattic/engine.io/issues/261 имеет гораздо больше информации, видимо, веб-сокеты действительно не требуют липких сессий, но длительный опрос делает. В нем также упоминается пара потенциальных обходов:

  • Откат назад к версии socket.io 0.9.17, которая сначала пытается использовать веб-сайты.
  • Использовать только SSL-соединения, которые делают веб-сайты более надежными (поскольку провайдеры и корпоративные прокси и не могут без труда подключаться к соединению).

Вы можете получить наилучшие результаты от объединения этих двух.

  • Вы также можете развернуть свой собственный балансировщик нагрузки, который добавит липкую поддержку сеанса, но к этому моменту вы сражаетесь с Heroku и можете быть лучше на другом хосте.

RE: ваш другой вопрос о модуле кластера Node.js: здесь это не помогло бы. Он для использования всех доступных ядер процессора на одном сервере/dyno,