2016-02-10 48 views
5

domanda in base a questa risposta: https://stackoverflow.com/a/18650183/4478897socket.io + Redis + expressjs grappolo - ottenere oggetto socket in expressjs richiedere

ho cercato di trovare questa soluzione, ma nulla sembra funzionare nel modo in cui ho bisogno.

Clustering expressjs e socket.io possiamo condividere le sessioni con Redis e inviare messaggi io all'interno io mondo (io.sockets.on('connection', ...). Il problema è se vogliamo inviare il messaggio (o utilizzare un semplice socket.join/leave) all'interno del mondo expressjs (route.get/post).

Se non stiamo usando cluster possiamo Atach l'oggetto client socket al request oggetto espresso (o semplicemente export l'oggetto io) e quindi utilizzarlo in qualsiasi momento su qualsiasi rotta GET/POST.

Al contrario, se siamo di clustering e utilizzare il metodo citato per ottenere l'oggetto socket all'interno del mondo expressjs, a volte l'oggetto socket è indefinito in quanto l'oggetto socket per questo client viene inizializzato in altri worker.

Qualche esempio di flusso:

  • client si connette al http://localhost e worker 1 gestisce questa richiesta.
  • Dopo aver caricato la pagina, il client si connette a socket.io. Worker 2 gestisce questa connessione.
  • Il client esegue un POST e di nuovo worker 1 o worker X gestisce questa richiesta.

In questo caso quando il client fare il POST, solo il worker 2 conosce l'oggetto socket per questo client. Quindi questo otterrà un oggetto non definito socket.

Quindi, la domanda:

Come possiamo ottenere l'oggetto client socket da qualsiasi worker di riutilizzare su expressjs request oggetto.

Forse il mio codice è sbagliato ma è quasi come il link alla risposta di cui sopra.


note

  • non si desidera utilizzare una sorta di proxy.
  • non vogliono migrare verso altre biblioteche (expressio, sockjs ...)
  • Ci dispiace per il mio inglese :)

Utilizzando ultimi nodejs, socket.io, expressjs, socket.io- redis, redis ... versioni

Non esitate a chiedere qualcosa!


UPDATE 1

Possibile soluzione, ma ancora bisogno di testarlo. Non so se questa è davvero una buona soluzione.

  • UPDATE 3: codice di lavoro per conto mio risposta

UPDATE 2

come aggiornamento 1 ma utilizzando https://nodejs.org/dist/latest-v5.x/docs/api/cluster.html#cluster_event_message

risposta

-1

Bene finalmente provato il codice e funziona (con alcune modifiche di misspells e altre cose) ma sono sicuro che deve essere un codice migliore da qualche parte. Quindi sono aperto a più risposte!

Questo codice è parte del mio modulo socket.io quando autorizzare il socket client e alcune altre cose ...

var redis = require("redis"); 
    var redisPub = redis.createClient(); 
    var redisSub = redis.createClient(); 
    var PubSubChannel = "clusterChannel"; 

    // Function that checks if this worker knows the socket object of this socketId. 
    // If not, publish the message to all the other sockets (workers) 
    io.socketDo = function (type, socketId, roomName) { 
    if (typeof io.sockets.connected[socketId] != "undefined") { 
     if (type === "join") { 
     return io.sockets.connected[socketId].join(roomName); 
     } 
     if (type === "leave") { 
     return io.sockets.connected[socketId].leave(roomName); 
     } 
    } else { 
     redisPub.publish(
     PubSubChannel, 
     JSON.stringify({ 
      type: type, 
      socketId: '' + socketId, 
      roomName: roomName 
     }) 
    ); 
    } 
    }; 

    // Subscribe to some channel 
    redisSub.subscribe(PubSubChannel); 

    // When this worker receive a message from channel "PubSubChannel" checks 
    // if it have the socket object for this socketId and do the operation 
    redisSub.on("message", function (channel, data) { 
    data = JSON.parse(data); 
    var type = data.type; 
    var socketId = data.socketId; 
    var roomName = data.roomName; 
    if ((type === "join" || type === "leave") && channel == PubSubChannel){ 
     if (typeof io.sockets.connected[socketId] != "undefined") { 
     if (type === "join") { 
      return io.sockets.connected[socketId].join(roomName); 
     } 
     if (type === "leave") { 
      return io.sockets.connected[socketId].leave(roomName); 
     } 
     } 
    } 
    }); 

Poi basta semplicemente esportare il modulo e collegare al vostro expressjs request => req.io = io

// req.session.socketId value is fetched on "io.sockets.on('connection', function(socket) {" 
// by express to socket.io using redis shared sessions 
app.get('/', function (req, res) { 
    req.io.socketDo('join', req.session.socketId, 'someRoomToJoin'); 

    // IT WORKS! 
    req.io.sockets.in('someRoomToJoin').emit('text'); 

    req.io.socketDo('leave', req.session.socketId, 'someRoomToLeave'); 
    res.send('Hello World!'); 
}); 
1

remoteJoin e remoteLeave metodi sono stati aggiunti in socket.io-Redis 3.0.0:

io.adapter.remoteJoin('<my-id>', 'room1', function (err) { 
    if (err) { /* unknown id */ } 
    // success 
}); 

io.adapter.remoteLeave('<my-id>', 'room1', function (err) { 
    if (err) { /* unknown id */ } 
    // success 
}); 

Nota: l'implementazione sembra molto (si spera?) Come la risposta above.

+0

ho visto l'unione. Grazie comunque: D – nada