web-dev-qa-db-de.com

Verwendung von Redis als PubSub über Socket.io

Ich erstelle eine Chat-Anwendung, mit der Benutzer private Chats und Gruppen chatten können. Planen Sie die Verwendung folgender Technologien für diese App: -

NodeJs + Socket.io + Redis + CouchDB (zum Speichern des Nachrichtenverlaufs) + AngularJS

Nach meinen ersten Recherchen mit Redis als PubSub-Dienst ist es besser, Socket.io als pub-sub zu verwenden. Grund dafür ist, wenn verschiedene Benutzer mit verschiedenen Serverinstanzen verbunden sind. Wenn Sie Socket in diesem Szenario verwenden, wird die Verwendung von Socket in diesem Szenario problematisch Benutzer 1 wird nicht an Benutzer 2 weitergegeben (Benutzer 1, der mit Server 1 verbunden ist, und Benutzer 2, der mit Server 2 verbunden ist).

Wenn wir Redis verwenden, müssen wir nach meinem Verständnis neue Kanäle erstellen, um private Chats zu ermöglichen. Und es gibt eine Begrenzung auf 10k Kanäle in Redis. 

Meine Zweifel sind

  1. Muss ich jedes Mal einen neuen Kanal erstellen, um den privaten Chat zwischen zwei Benutzern zu ermöglichen?
  2. Wenn ich separate Kanäle erstellen muss, gibt es tatsächlich ein Limit von 10K-Kanälen?
  3. Ich brauche ein funktionierendes Beispiel für die Verwendung von Redis als pub/sub mit socket.io, um private Chats zu ermöglichen.

Grüße, Vikram

13
VikramK

Nach dem Lesen der folgenden Artikel/Blogbeiträge hilft die Verwendung von Redis für pub/sub über socket.io pub/sub in der Skalierbarkeit und der besseren Leistung. 

https://github.com/sayar/RedisMVA/blob/master/module6_redis_pubsub/README.md

https://github.com/rajaraodv/redispubsub

Außerdem kann ich mit redis einen schnellen POC im privaten Chat erstellen. Hier ist der Code: -

var app = require('http').createServer(handler);
app.listen(8088);
var io = require('socket.io').listen(app);
var redis = require('redis');
var redis2 = require('socket.io-redis');
io.adapter(redis2({ Host: 'localhost', port: 6379 }));
var fs = require('fs');

function handler(req,res){
    fs.readFile(__dirname + '/index.html', function(err,data){
        if(err){
            res.writeHead(500);
            return res.end('Error loading index.html');
        }
        res.writeHead(200);
        console.log("Listening on port 8088");
        res.end(data);
    });
}

var store = redis.createClient();   
var pub = redis.createClient();
var sub = redis.createClient();
sub.on("message", function (channel, data) {
        data = JSON.parse(data);
        console.log("Inside Redis_Sub: data from channel " + channel + ": " + (data.sendType));
        if (parseInt("sendToSelf".localeCompare(data.sendType)) === 0) {
             io.emit(data.method, data.data);
        }else if (parseInt("sendToAllConnectedClients".localeCompare(data.sendType)) === 0) {
             io.sockets.emit(data.method, data.data);
        }else if (parseInt("sendToAllClientsInRoom".localeCompare(data.sendType)) === 0) {
            io.sockets.in(channel).emit(data.method, data.data);
        }       

    });

io.sockets.on('connection', function (socket) {

    sub.on("subscribe", function(channel, count) {
        console.log("Subscribed to " + channel + ". Now subscribed to " + count + " channel(s).");
    });

    socket.on("setUsername", function (data) {
        console.log("Got 'setUsername' from client, " + JSON.stringify(data));
        var reply = JSON.stringify({
                method: 'message',
                sendType: 'sendToSelf',
                data: "You are now online"
            });     
    });

    socket.on("createRoom", function (data) {
        console.log("Got 'createRoom' from client , " + JSON.stringify(data));
        sub.subscribe(data.room);
        socket.join(data.room);     

        var reply = JSON.stringify({
                method: 'message', 
                sendType: 'sendToSelf',
                data: "Share this room name with others to Join:" + data.room
            });
        pub.publish(data.room,reply);


    });
    socket.on("joinRooom", function (data) {
        console.log("Got 'joinRooom' from client , " + JSON.stringify(data));
        sub.subscribe(data.room);
        socket.join(data.room);     

    });
    socket.on("sendMessage", function (data) {
        console.log("Got 'sendMessage' from client , " + JSON.stringify(data));
        var reply = JSON.stringify({
                method: 'message', 
                sendType: 'sendToAllClientsInRoom',
                data: data.user + ":" + data.msg 
            });
        pub.publish(data.room,reply);

    });

    socket.on('disconnect', function () {
        sub.quit();
        pub.publish("chatting","User is disconnected :" + socket.id);
    });

  });

HTML Quelltext

<html>
<head>
    <title>Socket and Redis in Node.js</title>
    <script src="/socket.io/socket.io.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
</head>
<body>
<div id="username">
    <input type="text" name="usernameTxt" /> 
    <input type="button" name="setUsername" value="Set Username" />
</div>
<div id="createroom" style="display:none;">>
    <input type="text" name="roomNameTxt" /> 
    <input type="button" name="setRooomName" value="Set Room Name" />
    <input type="button" name="joinRooomName" value="Join" />
</div>
<div id="sendChat" style="display:none;">
    <input type="text" name="chatTxt" /> 
    <input type="button" name="sendBtn" value="Send" />
</div>
<br />
<div id="content"></div>
<script>    
    $(document).ready(function() {
        var username = "anonymous";
        var roomname = "anonymous";
        $('input[name=setUsername]').click(function(){
            if($('input[name=usernameTxt]').val() != ""){
                username = $('input[name=usernameTxt]').val();
                //var msg = {type:'setUsername',user:username};
                socket.emit('setUsername',{user:username});
            }
            $('#username').slideUp("slow",function(){
                $('#createroom').slideDown("slow");
            });
        });
        $('input[name=setRooomName]').click(function(){
            if($('input[name=roomNameTxt]').val() != ""){
                roomname = $('input[name=roomNameTxt]').val();
                socket.emit('createRoom',{user:username,room:roomname});
            }
            $('#createroom').slideUp("slow",function(){
                $('#sendChat').slideDown("slow");
            });
        });
        $('input[name=joinRooomName]').click(function(){
            if($('input[name=roomNameTxt]').val() != ""){
                roomname = $('input[name=roomNameTxt]').val();
                socket.emit('joinRooom',{room:roomname});
            }
            $('#createroom').slideUp("slow",function(){
                $('#sendChat').slideDown("slow");
            });
        });

        var socket = new io.connect('http://localhost:8088');
        var content = $('#content');

        socket.on('connect', function() {
            console.log("Connected");
        });

        socket.on('message', function(message){
            //alert('received msg=' + message);
            content.append(message + '<br />');
        }) ;

        socket.on('disconnect', function() {
            console.log('disconnected');
            content.html("<b>Disconnected!</b>");
        });

        $("input[name=sendBtn]").click(function(){
            var msg = {user:username,room:roomname,msg:$("input[name=chatTxt]").val()}
            socket.emit('sendMessage',msg);
            $("input[name=chatTxt]").val("");
        });
    });
</script>
</body>
</html>
16
VikramK

Das ist alles Code Basic Redis Pub/Sub.

var redis = require("redis");

var pub = redis.createClient();
var sub = redis.createClient();

sub.on("subscribe", function(channel, count) {
    console.log("Subscribed to " + channel + ". Now subscribed to " + count + " channel(s).");
});

sub.on("message", function(channel, message) {
    console.log("Message from channel " + channel + ": " + message);
});

sub.subscribe("tungns");

setInterval(function() {
    var no = Math.floor(Math.random() * 100);
    pub.publish('tungns', 'Generated Chat random no ' + no);
}, 5000);

3
NguyenTungs

Wenn Sie Ihre Füße nass machen und eine einfache Chat-Anwendung erstellen müssen, funktioniert der folgende Entwicklungsstack sehr gut:

  • Express.js (Node.js)
  • Redis
  • Socket.IO

Die Anwendung besteht aus einem Chatroom, an dem Benutzer teilnehmen und eine Konversation beginnen können. Socket.IO ist dafür verantwortlich, Ereignisse zu senden, wenn die Anzahl der Chatter-Meldungen aktualisiert wird und diese in der Benutzeroberfläche mit jQuery aktualisiert werden.

Den vollständigen Artikel und den Quellcode finden Sie unter folgendem Link: https://scalegrid.io/blog/using-redis-with-node-js-and-socket-io/

1
Kunal Nagar

Die socket.io-redis sagt:

Wenn Sie socket.io mit dem socket.io-redis-Adapter ausführen, können Sie mehrere socket.io-Instanzen in verschiedenen Prozessen oder Servern ausführen, die alle Ereignisse senden und voneinander ausgeben können. Also einen der folgenden Befehle:

io.emit('hello', 'to all clients');
io.to('room42').emit('hello', "to all clients in 'room42' room");

io.on('connection', (socket) => {
  socket.broadcast.emit('hello', 'to all clients except sender');
  socket.to('room42').emit('hello', "to all clients in 'room42' room except sender");
});

werden ordnungsgemäß über den Redis Pub/Sub-Mechanismus an die Clients übertragen.

und ich denke

io.to(socket.id).emit('hello', "to client which has same socket.id");

würde private Nachricht in verschiedenen Prozessen oder Servern senden.

Übrigens brauche ich für ein Projekt auch eine private Nachricht. Irgendwelche anderen Vorschläge möchten zur Sprache gebracht werden.

0
tingtinghuang