我应该怎么使用? Socket.io房间或Redis的发布 - 订阅?(What should

2019-07-20 01:31发布

很简单的问题。 我建立使用作为的NodeJS我的后端实时的比赛,我想知道是否有任何信息,请访问哪一个更可靠,哪一个更有效? 我大量使用Redis的双方和整个Socket.io我的代码。 所以,我想知道我是否应该利用Socket.io的房间或者我会关闭使用Redis的更好的发布-订阅 ?

更新:刚刚意识到有为什么您可能希望使用Redis的发布/订阅了socket.io房间一个很重要的原因。 随着当你发布到听众Socket.io房间,(浏览器)客户端收到消息,与Redis的它实际上是(Redis的〜在服务器上)的客户谁收到的消息。 出于这个原因,如果你想告知的信息,具体到每一个客户端的所有(服务器)客户端,并传递到浏览器客户端之前,也许做一些处理,你最好使用Redis的。 使用Redis的你可以只火了一个事件来生成每个用户的个人数据,其中与socket.io你必须真正生成所有的用户同时独特的数据,然后依次通过他们,并把他们自己的个人数据,这几乎违背了房间,至少对我的目的。

不幸的是,我的目的,我坚持Redis的现在。

更新2:截止开发了一个插件,只使用2 Redis的连接,但仍然允许个别客户端处理,请参阅下面回答....

Answer 1:

Redis的发布/订阅是巨大的情况下,所有的客户都Redis的直接访问。 如果有多个节点服务器,一个可以把一个消息给其他人。

但是,如果你也有客户在浏览器中,你需要的东西都可以从服务器将数据推送到客户端,在这种情况下,socket.io是伟大的。

现在,如果你使用socket.io与Redis的商店,socket.io将使用Redis的发布/订阅引擎盖下传播服务器之间的邮件,服务器将消息传播到客户端。

因此,使用与socket.io与Redis的商店配置socket.io房间可能是最简单的为您服务。



Answer 2:

我最后写一个节点插件,以便为众多的发布 - 订阅客户端,但只需要2个Redis的连接,而不是每一个socketio连接上一个新的,它应该在一般的工作,想出别人可能会觉得使用它。

此代码假设你有socket.io运行和设置,基本在这个例子中的任何数量的socket.io的客户端可以连接,它总是会仍然只使用2个Redis的连接,但所有客户端都可以订阅自己的渠道。 在这个例子中,所有的客户端收到一条消息,“甜蜜的消息!” 10秒后。

例如用socket.io(利用redis的发布 - 订阅):

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);

实际插件代码:

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;

我搞乱身边,并试图尽可能多的,因为我可以提高效率,但做一些不同的速度测试之后,我得出的结论,这是最快的,我能得到它。

要获得的最新版本: https://github.com/Jezternz/node-redis-pubsub



文章来源: What should I be using? Socket.io rooms or Redis pub-sub?