Ich schrieb ein Knoten-Plugin für viele Pub-Sub-Clients, aber nur 2 Redis-Verbindungen statt einer neuen auf jeder einzelnen Socket-Verbindung erforderlich, sollte es im Allgemeinen funktionieren, dachte jemand anders kann dafür Verwendung finden .
Dieser Code ging davon aus, dass Sie socket.io ausführen und einrichten, im Grunde können in diesem Beispiel beliebig viele socket.io Clients eine Verbindung herstellen und es werden immer nur 2 redis-Verbindungen verwendet, aber alle Clients können ihre eigenen Kanäle abonnieren. In diesem Beispiel erhalten alle Clients eine Nachricht "süße Nachricht!" nach 10 Sekunden.
Beispiel mit socket.io (redis pub-sub Nutzung):
var
RPubSubFactory = require('rpss.js');
var
redOne = redis.createClient(port, host),
redTwo = redis.createClient(port, host);
var pSCFactory = new RPubSubFactory(redOne);
io.sockets.on('connection', function(socket){
var cps = pSCFactory.createClient();
cps.onMessage(function(channel, message){
socket.emit('message', message);
});
io.sockets.on('disconnect', function(socket){
// Dont actually need to unsub, because end() will cleanup all subs,
// but if you need to sometime during the connection lifetime, you can.
cps.unsubscribe('cool_channel');
cps.end();
});
cps.subscribe('cool_channel')
});
setTimeout(function(){
redTwo.publish('cool_channel', 'sweet message!');
},10000);
Actual Plugin-Code:
var RPubSubFactory = function(){
var
len,indx,tarr;
var
dbcom = false,
rPubSubIdCounter = 1,
clientLookup = {},
globalSubscriptions = {};
// public
this.createClient = function()
{
return new RPubSupClient();
}
// private
var constructor = function(tdbcom)
{
dbcom = tdbcom;
dbcom.on("message", incommingMessage);
}
var incommingMessage = function(rawchannel, strMessage)
{
len = globalSubscriptions[rawchannel].length;
for(var i=0;i<len;i++){
//console.log(globalSubscriptions[rawchannel][i]+' incomming on channel '+rawchannel);
clientLookup[globalSubscriptions[rawchannel][i]]._incommingMessage(rawchannel, strMessage);
}
}
// class
var RPubSupClient = function()
{
var
id = -1,
localSubscriptions = [];
this.id = -1;
this._incommingMessage = function(){};
this.subscribe = function(channel)
{
//console.log('client '+id+' subscribing to '+channel);
if(!(channel in globalSubscriptions)){
globalSubscriptions[channel] = [id];
dbcom.subscribe(channel);
}
else if(globalSubscriptions[channel].indexOf(id) == -1){
globalSubscriptions[channel].push(id);
}
if(localSubscriptions.indexOf(channel) == -1){
localSubscriptions.push(channel);
}
}
this.unsubscribe = function(channel)
{
//console.log('client '+id+' unsubscribing to '+channel);
if(channel in globalSubscriptions)
{
indx = globalSubscriptions[channel].indexOf(id);
if(indx != -1){
globalSubscriptions[channel].splice(indx, 1);
if(globalSubscriptions[channel].length == 0){
delete globalSubscriptions[channel];
dbcom.unsubscribe(channel);
}
}
}
indx = localSubscriptions.indexOf(channel);
if(indx != -1){
localSubscriptions.splice(indx, 1);
}
}
this.onMessage = function(msgFn)
{
this._incommingMessage = msgFn;
}
this.end = function()
{
//console.log('end client id = '+id+' closing subscriptions='+localSubscriptions.join(','));
tarr = localSubscriptions.slice(0);
len = tarr.length;
for(var i=0;i<len;i++){
this.unsubscribe(tarr[i]);
}
localSubscriptions = [];
delete clientLookup[id];
}
var constructor = function(){
this.id = id = rPubSubIdCounter++;
clientLookup[id] = this;
//console.log('new client id = '+id);
}
constructor.apply(this, arguments);
}
constructor.apply(this, arguments);
};
module.exports = RPubSubFactory;
ich muckte um und versuchte, die Effizienz so viel wie ich konnte zu verbessern, aber nachdem ich verschiedene Geschwindigkeitstests durchgeführt hatte, kam ich zu dem Schluss, dass dies der schnellste war, den ich bekommen konnte.
Für up-to-date-Version: https://github.com/Jezternz/node-redis-pubsub
interessante Frage, ich würde auch gerne wissen. wahrscheinlich würde dieser Beitrag eine Hilfe sein: http://StackOverflow.com/Questions/10167206/Redis-Pub-Sub-Or-Socket-IOS-broadcast – yuwang
Danke für den Link, der letzte Beitrag macht einen guten Punkt. Möglicherweise weniger skalierbar für die Verwendung von socket.io, da der (Prozess-) Umfang eingeschränkt sein könnte. –
Kann jemand die Unterschiede erklären? Details wären nett. – user568109