L'autorisation de socket web Socket.io échoue lors de l'application de nœud de clustering

Question: Est-il possible de regrouper une application qui utilise Socket.io pour la prise en charge WebSocket? Si oui, quelle serait la meilleure méthode de mise en œuvre?

J'ai construit une application qui utilise Express et Socket.io, construit sur Node.js. J'aimerais intégrer le clustering pour augmenter le nombre de demandes que mon application peut traiter.

Ce qui suit provoque mon application pour produire une erreur de prise de contact socket …

var cluster = require('cluster'); var numCPUs = require('os').cpus().length; if (cluster.isMaster) { // Fork workers. for (var i = 0; i < numCPUs; i++) { cluster.fork(); } cluster.on('death', function(worker) { console.log('worker ' + worker.pid + ' died'); }); } else { app.listen(3000); } 

Un journal de console montre que socket.io est lancé à plusieurs reprises.

 jack@jack:~$ node nimble/app.js info - socket.io started info - socket.io started info - socket.io started info - socket.io started info - socket.io started info - socket.io started info - socket.io started info - socket.io started info - socket.io started 

Socket.io est en cours de configuration en haut de mon code de serveur en utilisant:

 var io = require('socket.io').listen(app); 

Le code d'autorisation du websocket:

 //Auth the user io.set('authorization', function (data, accept) { // check if there's a cookie header if (data.headers.cookie) { data.cookie = parseCookie(data.headers.cookie); data.sessionID = data.cookie['express.sid']; //Save the session store to the data object data.sessionStore = sessionStore; sessionStore.get(data.sessionID, function(err, session){ if(err) throw err; if(!session) { console.error("Error whilst authorizing websocket handshake"); accept('Error', false); } else { console.log("AUTH USERNAME: " + session.username); if(session.username){ data.session = new Session(data, session); accept(null, true); }else { accept('Invalid User', false); } } }) } else { console.error("No cookie was found whilst authorizing websocket handshake"); return accept('No cookie transmitted.', false); } }); 

Journal de la console du message d'erreur:

 Error whilst authorizing websocket handshake debug - authorized warn - handshake error Error 

Quel est votre sessionStore ? Si c'est le MemoryStore livré avec connect , les sessions ne seront pas partagées entre vos travailleurs. Chaque travailleur aura son propre ensemble de sessions, et si un client se connecte à un autre travailleur, vous ne trouverez pas sa session. Je vous suggère de jeter un coup d'oeil, par exemple, connect-redis pour partager des sessions entre les processus. Utilisation de base:

 var connect = require('connect') , RedisStore = require('connect-redis')(connect); var app = connect.createServer(); app.use(connect.session({store: new RedisStore, secret: 'top secret'}); 

Bien sûr, cela exige que vous configurez également des redis. Sur le wiki Connect, il existe des modules pour CouchDB, memcached, postgres et autres.

Cela résout seulement une partie de votre problème, car maintenant vous avez des sessions partagées entre les travailleurs, mais socket.io n'a aucun moyen d'envoyer des messages aux clients qui sont connectés à d'autres travailleurs. Fondamentalement, si vous socket.emit un socket.emit dans un travailleur, ce message ne sera envoyé qu'aux clients connectés à ce même travailleur. Une solution à cela est d'utiliser RedisStore pour socket.io , qui exploite redis pour acheminer les messages entre les travailleurs. Utilisation de base:

 var sio = require('socket.io') , RedisStore = sio.RedisStore , io = sio.listen(app); io.set('store', new RedisStore); 

Maintenant, tous les messages doivent être acheminés vers les clients quel que soit le travailleur auquel ils sont connectés.

Voir aussi: Node.js, multi-threading et Socket.io