Ich empfange doppelte Nachrichten in meinem Clustered Node.js/Socket.io/Redis Pub/Sub Application

StackOverflow https://stackoverflow.com/questions/8363242

  •  27-10-2019
  •  | 
  •  

Frage

Ich verwende Node.js, Socket.io mit RedisStore, Cluster aus den Jungs von Socket.io und Redis.

Ich habe eine Pub/Sub -Anwendung, die auf nur einem Knoten.js -Knoten gut funktioniert. Wenn es jedoch unter starker Belastung geht, ist maximal nur ein Kern des Servers, da Node.js nicht für Multi-Core-Maschinen geschrieben wird.

Wie Sie unten sehen können, verwende ich jetzt das Cluster -Modul von LearnBoost, denselben Personen, die Socket.io machen.

Wenn ich jedoch 4 Arbeiterprozesse abfeuere, erhält jeder Browser -Client, der hereinkommt und abonniert, 4 Kopien jeder in Redis veröffentlichten Nachricht. Wenn es drei Arbeiterprozesse gibt, gibt es drei Kopien.

Ich vermute, ich muss die Redis Pub/Sub -Funktionalität irgendwie in die cluster.js -Datei verschieben.

Cluster.js

var cluster = require('./node_modules/cluster');

cluster('./app')
  .set('workers', 4)
  .use(cluster.logger('logs'))
  .use(cluster.stats())
  .use(cluster.pidfiles('pids'))
  .use(cluster.cli())
  .use(cluster.repl(8888))
  .listen(8000);

App.js

redis = require('redis'),
sys = require('sys');

var rc = redis.createClient();

var path = require('path')
  , connect = require('connect')
  , app = connect.createServer(connect.static(path.join(__dirname, '../')));

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

io.set('store', new RedisStore);io.sockets.on('connection', function(socket) {
    sys.log('ShowControl -- Socket connected: ' + socket.id);

    socket.on('channel', function(ch) {
        socket.join(ch)
        sys.log('ShowControl -- ' + socket.id + ' joined channel: ' + ch);
    });

    socket.on('disconnect', function() {
        console.log('ShowControll -- Socket disconnected: ' + socket.id);
    });
});

rc.psubscribe('showcontrol_*');

rc.on('pmessage', function(pat, ch, msg) {
    io.sockets.in(ch).emit('show_event', msg);
    sys.log('ShowControl -- Publish sent to channel: ' + ch);
});

// cluster compatiblity
if (!module.parent) {
  app.listen(process.argv[2] || 8081);
  console.log('Listening on ', app.address());
} else {
  module.exports = app;
}

client.html

<script src="http://localhost:8000/socket.io/socket.io.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js"></script>
<script>
    var socket = io.connect('localhost:8000');
    socket.emit('channel', 'showcontrol_106');
    socket.on('show_event', function (msg) {
        console.log(msg);
        $("body").append('<br/>' + msg);
    });
</script>
War es hilfreich?

Lösung 2

Es stellt sich heraus, dass dies kein Problem mit node.js/socket.io ist, ich habe es einfach völlig falsch gemacht.

Ich habe nicht nur den REDIS -Server von außerhalb des Knoten-/Socket -Stacks auf den REDIS -Server veröffentlicht, sondern auch direkt mit dem Redis -Kanal abonniert. An beiden Enden der Pub/Sub -Situation umging ich den "Socket.io -Cluster mit Redis Store am Back End" Güte.

Also habe ich eine kleine App (mit node.js/socket.io/express) erstellt, die Nachrichten von meiner Rails-App aufgenommen und sie mit dem Socket.io-Announce-Modul in einen Socket.io-Raum "angekündigt". Durch die Verwendung von Socket.io -Routing -Magie erhielt und sendet jeder Knotenarbeiter nur Nachrichten an Browser, die direkt mit ihnen verbunden sind. Mit anderen Worten, keine mehr doppelten Nachrichten, da sowohl das Kneipe als auch das Sub innerhalb des Node.js/Socket.io -Stacks stattgefunden haben.

Nachdem ich meinen Code aufgeräumt habe, werde ich irgendwo ein Beispiel für einen Github aufstellen.

Andere Tipps

Ich habe mit Cluster und Socket.io gekämpft. Jedes Mal, wenn ich die Clusterfunktion verwende (ich verwende jedoch den integrierten NodeJS -Cluster), erhalte ich viele Leistungsprobleme und Probleme mit Socket.io.

Während ich versuchte, dies zu erforschen, habe ich die Fehlerberichte und ähnlich auf dem Socket.io Git gegraben, und jeder, der Cluster oder externe Lastbalancer auf ihre Server verwendet, scheint Probleme mit Socket.io zu haben.

Es scheint das Problem zu erzeugen "Client nicht Handschüttungs -Client sollte sich wieder verbinden", was Sie sehen, wenn Sie die ausführliche Protokollierung erhöhen. Dies erscheint viel, wenn Socket.io in einem Cluster läuft, so dass ich denke, dass es wieder darauf zurückkehrt. IE Der Client wird jedes Mal mit randomisierter Instanz im Socket.IO -Cluster verbunden, wenn er eine neue Verbindung herstellt (es führt bei der autorisierenden Autorisierung und mehr die Zeit später, wenn sie nach neuen Daten befragt werden).

Derzeit habe ich zurückgekehrt, um jeweils nur 1 Socket.IO -Prozess zu verwenden. Dies könnte ein Fehler sein, könnte aber auch ein Mangel an der Erstellung von Socket.io sein.

Hinzugefügt: Meine Art, dies in Zukunft zu lösen, besteht darin, jeder Socket.IO -Instanz im Cluster einen eindeutigen Port zuzuweisen und dann auf der Client -Seite zu cache -Port -Auswahl.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top