sql >> Database teknologi >  >> NoSQL >> Redis

Node.js, Socket.io, Redis pub/sub høj lydstyrke, lav latency vanskeligheder

Jeg syntes det var et rimeligt spørgsmål og havde undersøgt det kort for et stykke tid siden. Jeg brugte lidt tid på at søge efter eksempler, som du måske kunne hente nogle nyttige tips fra.

Eksempler

Jeg kan godt lide at begynde med ligefrem eksempler:

  • Light im eksempelkode
  • Node.js + Redis Pub/Sub + socket.io demo

Lyseksemplet er en enkelt side (bemærk, at du vil erstatte redis-node-client med noget som node_redis af Matt Ranney:

/*
 * Mclarens Bar: Redis based Instant Messaging
 * Nikhil Marathe - 22/04/2010

 * A simple example of an IM client implemented using
 * Redis PUB/SUB commands so that all the communication
 * is offloaded to Redis, and the node.js code only
 * handles command interpretation,presentation and subscribing.
 * 
 * Requires redis-node-client and a recent version of Redis
 *    http://code.google.com/p/redis
 *    http://github.com/fictorial/redis-node-client
 *
 * Start the server then telnet to port 8000
 * Register with NICK <nick>, use WHO to see others
 * Use TALKTO <nick> to initiate a chat. Send a message
 * using MSG <nick> <msg>. Note its important to do a
 * TALKTO so that both sides are listening. Use STOP <nick>
 * to stop talking to someone, and QUIT to exit.
 *
 * This code is in the public domain.
 */
var redis = require('./redis-node-client/lib/redis-client');

var sys = require('sys');
var net = require('net');

var server = net.createServer(function(stream) {
    var sub; // redis connection
    var pub;
    var registered = false;
    var nick = "";

    function channel(a,b) {
    return [a,b].sort().join(':');
    }

    function shareTable(other) {
    sys.debug(nick + ": Subscribing to "+channel(nick,other));
    sub.subscribeTo(channel(nick,other), function(channel, message) {
        var str = message.toString();
        var sender = str.slice(0, str.indexOf(':'));
        if( sender != nick )
        stream.write("[" + sender + "] " + str.substr(str.indexOf(':')+1) + "\n");
    });
    }

    function leaveTable(other) {
    sub.unsubscribeFrom(channel(nick,other), function(err) {
        stream.write("Stopped talking to " + other+ "\n");
    });
    }

    stream.addListener("connect", function() {
    sub = redis.createClient();
    pub = redis.createClient();
    });

    stream.addListener("data", function(data) {
    if( !registered ) {
        var msg = data.toString().match(/^NICK (\w*)/);
        if(msg) {
        stream.write("SERVER: Hi " + msg[1] + "\n");
        pub.sadd('mclarens:inside', msg[1], function(err) {
            if(err) {
            stream.end();
            }
            registered = true;
            nick = msg[1];
// server messages
            sub.subscribeTo( nick + ":info", function(nick, message) {
            var m = message.toString().split(' ');
            var cmd = m[0];
            var who = m[1];
            if( cmd == "start" ) {
                stream.write( who + " is now talking to you\n");
                shareTable(who);
            }
            else if( cmd == "stop" ) {
                stream.write( who + " stopped talking to you\n");
                leaveTable(who);
            }
            });
        });
        }
        else {
        stream.write("Please register with NICK <nickname>\n");
        }
        return;
    }

    var fragments = data.toString().replace('\r\n', '').split(' ');
    switch(fragments[0]) {
    case 'TALKTO':
        pub.publish(fragments[1]+":info", "start " + nick, function(a,b) {
        });
        shareTable(fragments[1]);
        break;
    case 'MSG':
        pub.publish(channel(nick, fragments[1]),
            nick + ':' +fragments.slice(2).join(' '),
              function(err, reply) {
              if(err) {
                  stream.write("ERROR!");
              }
              });
        break;
    case 'WHO':
        pub.smembers('mclarens:inside', function(err, users) {
        stream.write("Online:\n" + users.join('\n') + "\n");
        });
        break;
    case 'STOP':
        leaveTable(fragments[1]);
        pub.publish(fragments[1]+":info", "stop " + nick, function() {});
        break;
    case 'QUIT':
        stream.end();
        break;
    }
    });

    stream.addListener("end", function() {
    pub.publish(nick, nick + " is offline");
    pub.srem('mclarens:inside', nick, function(err) {
        if(err) {
        sys.debug("Could not remove client");
        }
    });
    });
});

server.listen(8000, "localhost");

Dokumenter

Der er et væld af dokumentation derude, og API'erne ændrer sig hurtigt på denne type stak, så du bliver nødt til at afveje tidsrelevansen for hvert dokument.

  • knudeaktivitetsstrømme
  • eksempel på skystøberi
  • hvordan node redis pubsub
  • redis latens
  • redis kogebog Brug af Pub/Sub til asynkron kommunikation
  • linkedins generiske tips
  • node redis-bindinger
  • google grupper nodejs spørgsmål

Relaterede spørgsmål

Bare et par relaterede spørgsmål, dette er et varmt emne på stakken:

  • Redis pub/sub til chatserver i node.js
  • Hvordan designer man redis pub/sub til et onlinemeddelelsessystem?

Bemærkelsesværdige tip (ymmv)

Sluk eller optimer socket-pooling, brug effektive bindinger, overvåg latens, og sørg for, at du ikke dublerer arbejde (dvs. ingen grund til at udgive til alle lyttere to gange).




  1. MongoDB Whitespace-tegn

  2. Node JS Redis Client Connection Prøv igen

  3. Redis `SCAN`:hvordan opretholder man en balance mellem nye kommende nøgler, der kan matche og sikre et endeligt resultat inden for en rimelig tid?

  4. Mongoose:CastError:Cast to ObjectId mislykkedes for værdien [object Object] ved sti _id