Socket.io и несколько Dyno на Heroku Node.js. WebSocket закрывается до установления соединения
Я создаю приложение, развернутое в Heroku, которое использует Websockets.
Соединение websockets работает правильно, когда я использую только 1 dyno, но когда я масштабируюсь до > 1, я получаю следующие ошибки.
POST HTTP://****.herokuapp.com/socket.io/EIO = 2 & транспорт = опроса & т = 1412600135378-1 & ИСС = zQzJJ8oPo5p3yiwIAAAC 400 (неверный запрос) socket.io-1.0.4.js: 2
Подключение к WebSocket для 'WS://****.herokuapp.com/socket.io/EIO = 2 & транспорт = WebSocket & ИСС = zQzJJ8oPo5p3yiwIAAAC? failed: WebSocket закрыт до установления соединения. socket.io-1.0.4.js: 2
Я использую адаптер Redis для включения нескольких веб-процессов.
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}) );
Это работает на localhost (я использую мастера для запуска, как это делает Heroku, и я запускаю 2 веб-процесса, как и на Heroku).
Прежде чем я применил адаптер redis, у меня возникла ошибка установления связи с веб-сокетами, поэтому адаптер имел некоторый эффект. Кроме того, он работает время от времени, я предполагаю, когда сокеты соответствуют одному и тому же веб-дино.
Я также пытался включить липкие сессии, но потом он никогда не работает.
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);
});
Ответы
Ответ 1
Я являюсь владельцем платформы Node.js в Heroku.
WebSockets работает на Heroku из-за коробки через несколько динамиков; socket.io(и другие библиотеки реального времени) используют резервные копии для процессов без учета состояния, таких как опрос xhr, которые прерываются без привязки к сеансу.
Чтобы масштабировать приложения socket.io, сначала следуйте всем инструкциям из socket.io:
Затем включите поддержку сеанса в своем приложении (это бесплатная функция):
Ответ 2
Я потратил некоторое время, пытаясь заставить socket.io работать в многосерверной архитектуре, сначала на Heroku, а затем на Openshift, как говорят многие.
Единственный способ заставить его работать на обоих PAAS - это отключить xhr-опрос и установить transports: ['websocket']
как на клиенте, так и на сервере.
В Openshift вы должны явно установить порт сервера на 8000 (для ws - 8443 для wss при инициализации клиента 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']);
на стороне клиента:
var ioSocket = io('<your-openshift-app>.rhcloud.com:8000' || '<your-heroku-app>.herokuapp.com', {
path: '/socket.io-client'
transports: ['websocket']
})
Надеюсь, это поможет.
Ответ 3
Возможно, вам нужно запустить RedisStore:
var session = require('express-session');
var RedisStore = require('connect-redis')(session);
app.use(session({
store: new RedisStore(options),
secret: 'keyboard cat'
}));
за предыдущий q здесь: Несколько динамиков на передачах Heroku + socket.io
Ответ 4
Я знаю, что это не обычный ответ, но я пытался получить WebSockets, работающий на Heroku более недели. После долгих разговоров с поддержкой клиентов я, наконец, попробовал OpenShift. Heroku WebSockets находятся в бета-версии, но OpenShift WebSockets стабильны. Я получил код, работающий на OpenShift менее чем через час.
http://www.openshift.com
Я не отношусь к OpenShift каким-либо образом. Я просто довольный (неоплачиваемый) клиент.
Ответ 5
У меня были огромные проблемы с этим. Одновременно возникло множество проблем, что сделало его огромным кошмаром. Убедитесь, что для масштабирования socket.io на heroku выполните следующие действия:
Для вас и других это может быть любой из них.
Если у вас возникли проблемы с настройкой кластеров с липкой сессией, здесь мой рабочий код
var http = require('http');
var cluster = require('cluster');
var numCPUs = require('os').cpus().length;
var sticky = require('socketio-sticky-session');
var redis = require('socket.io-redis');
var io;
if(cluster.isMaster){
console.log('Inside Master');
// create the worker processes
for (var i = 0; i < numCPUs ; i++){
cluster.fork();
}
}
else {
// The worker code to be run is written inside
// the sticky().
}
sticky(function(){
// This code runs inside the workers.
// The sticky-session balances connection between workers based on their ip.
// So all the requests from the same client would go to the same worker.
// If multiple browser windows are opened in the same client, all would be
// redirected to the same worker.
io = require('socket.io')({transports:'websocket', 'origins' : '*:*'});
var server = http.createServer(function(req,res){
res.end('socket.io');
})
io.listen(server);
// The Redis server can also be used to store the socket state
//io.adapter(redis({host:'localhost', port:6379}));
console.log('Worker: '+cluster.worker.id);
// when multiple workers are spawned, the client
// cannot connect to the cloudlet.
StartConnect(); //this function connects my mongodb, then calls a function with io.on('connection', ..... socket.on('message'...... in relation to the io variable above
return server;
}).listen(process.env.PORT || 4567, function(){
console.log('Socket.io server is up ');
});
Дополнительная информация:
лично он работал бы безупречно с сеанса, не используя websockets (я использую socket.io для игры с единством. Он работал безупречно из редактора!). При подключении через браузер, будь то хром или firefox, он будет показывать эти ошибки установления связи, а также ошибки 503 и 400.