Подтвердить что ты не робот

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);
});
4b9b3361

Ответ 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']
})

Надеюсь, это поможет.

Ответ 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.