2016-02-05 2 views
0

Хорошо, у меня есть API с расширенным питанием, где у меня также есть socket.io, работающий для приема/отправки событий в реальном времени ... все работает просто dandy. Мне нужно сгруппировать мое приложение. Я настроил все на основе приведенного ниже кода. Я разворачиваю рабочих, они получают связи, и все работает, за исключением того, что теперь я не могу «взорвать» все соединения socket.io. Вот установка (взято из this):Проблема с узлом кластера с использованием Socket.io и Redis

var express = require('express'), 
    cluster = require('cluster'), 
    net = require('net'), 
    sio = require('socket.io'), 
    sio_redis = require('socket.io-redis'); 

var port = 3000, 
    num_processes = require('os').cpus().length; 

if (cluster.isMaster) { 
    // This stores our workers. We need to keep them to be able to reference 
    // them based on source IP address. It's also useful for auto-restart, 
    // for example. 
    var workers = []; 

    // Helper function for spawning worker at index 'i'. 
    var spawn = function(i) { 
     workers[i] = cluster.fork(); 

     // Optional: Restart worker on exit 
     workers[i].on('exit', function(worker, code, signal) { 
      console.log('respawning worker', i); 
      spawn(i); 
     }); 
    }; 

    // Spawn workers. 
    for (var i = 0; i < num_processes; i++) { 
     spawn(i); 
    } 

    // Helper function for getting a worker index based on IP address. 
    // This is a hot path so it should be really fast. The way it works 
    // is by converting the IP address to a number by removing the dots, 
    // then compressing it to the number of slots we have. 
    // 
    // Compared against "real" hashing (from the sticky-session code) and 
    // "real" IP number conversion, this function is on par in terms of 
    // worker index distribution only much faster. 
    var workerIndex = function (ip, len) { 
    var _ip = ip.split(/['.'|':']/), 
     arr = []; 

    for (el in _ip) { 
     if (_ip[el] == '') { 
      arr.push(0); 
     } 
     else { 
      arr.push(parseInt(_ip[el], 16)); 
     } 
    } 

    return Number(arr.join('')) % len; 
} 

    // Create the outside facing server listening on our port. 
    var server = net.createServer({ pauseOnConnect: true }, function(connection) { 
     // We received a connection and need to pass it to the appropriate 
     // worker. Get the worker for this connection's source IP and pass 
     // it the connection. 
     var worker = workers[worker_index(connection.remoteAddress, num_processes)]; 
     worker.send('sticky-session:connection', connection); 
    }).listen(port); 
} else { 
    // Note we don't use a port here because the master listens on it for us. 
    var app = new express(); 

    // Here you might use middleware, attach routes, etc. 

    // Don't expose our internal server to the outside. 
    var server = app.listen(0, 'localhost'), 
     io = sio(server); 

    // Tell Socket.IO to use the redis adapter. By default, the redis 
    // server is assumed to be on localhost:6379. You don't have to 
    // specify them explicitly unless you want to change them. 
    io.adapter(sio_redis({ host: 'localhost', port: 6379 })); 

    // Here you might use Socket.IO middleware for authorization etc. 

    // Listen to messages sent from the master. Ignore everything else. 
    process.on('message', function(message, connection) { 
     if (message !== 'sticky-session:connection') { 
      return; 
     } 

     // Emulate a connection event on the server by emitting the 
     // event with the connection the master sent us. 
     server.emit('connection', connection); 

     connection.resume(); 
    }); 
} 

Так я подключаю от различных машин для проверки параллельности, рабочие делают свое дело, и все это хорошо, но когда я получаю соединение IO, я протоколирование TOTAL «подключено», и оно всегда 1 на экземпляр. Мне нужен способ, чтобы сказать

allClusterForks.emit(stuff) 

я получаю соединение на правильный рабочий ФИД, но «ВСЕ СОЕДИНЕНИЯ» всегда возвращает 1.

io.on('connection', function(socket) { 
    console.log('Connected to worker %s', process.pid); 
    console.log("Adapter ROOMS %s ", io.sockets.adapter.rooms); 
    console.log("Adapter SIDS %s ", io.sockets.adapter.sids); 
    console.log("SOCKETS CONNECTED %s ", Object.keys(io.sockets.connected).length); 
}); 

Я могу видеть подписаться/отказаться от подписки в ближайшие используя Redis MONITOR

1454701383.188231 [0 127.0.0.1:63150] "subscribe" "socket.io#/#gXJscUUuVQGzsYJfAAAA#" 
1454701419.130100 [0 127.0.0.1:63167] "subscribe" "socket.io#/#geYSvYSd5zASi7egAAAA#" 
1454701433.842727 [0 127.0.0.1:63167] "unsubscribe" "socket.io#/#geYSvYSd5zASi7egAAAA#" 
1454701444.630427 [0 127.0.0.1:63150] "unsubscribe" "socket.io#/#gXJscUUuVQGzsYJfAAAA#" 

эти соединения от 2-х разных машин, я бы ожидать, с помощью разъема адаптера IO Redis, что эти подписки будет приходить в том же соединении Redis, но они ар другие.

Я просто что-то пропустил? Существует удивительное отсутствие документации/статей для этого, которые не являются полностью устаревшими/неправильными/неоднозначными.

EDIT: Узел v5.3.0 Redis v3.0.6 Socket.io v1.3.7

ответ

0

Так что, если кто-то приходит через это, я понял, что на самом деле «смотрит» на эпизодах связанных сокетов между процессами это не вещь, а передача или излучение. Поэтому я просто просто «тестировал» без причины. Все работает так, как ожидалось. Я буду переписывать адаптер socket.io-redis, чтобы проверять количество отсчетов между процессами.

Несколько лет назад был запрос на оттяжку, чтобы реализовать поддержку того, что я пытался сделать. https://github.com/socketio/socket.io-redis/pull/15, и я мог бы попробовать очистить его и повторно отправить.

Смежные вопросы