Node.js,Socket.io,Redis pub/sub高容量,低延迟困难

当连接socket.io/node.js和redis pub / sub试图创建一个由可以处理多个传输的服务器事件驱动的实时Web广播系统时,似乎有三种方法:

>’createClient’a redis连接并订阅频道。在socket.io客户端连接上,将客户端连接到socket.io空间。在redis.on(“message”,…)事件中,调用io.sockets.in(room).emit(“event”,data)分发给相关房间中的所有客户端。喜欢How to reuse redis connection in socket.io?
>’createClient’一个redis连接。在socket.io客户端连接上,将客户端连接到socket.io房间并订阅相关的redis通道。在客户端连接闭包内包含redis.on(“message”,…),并在收到消息时调用client.emit(“event”,data)以在特定客户端上引发事件。喜欢Examples in using RedisStore in socket.io的答案
>根据socketio-spec协议,使用RedisStore烘焙到socket.io和redis中的单个“dispatch”通道的’broadcast’。

数字1允许为所有客户端处理一次Redis子和相关事件。数字2提供了一个更直接的钩到Redis pub / sub。数字3更简单,但对消息事件几乎没有控制。

然而,在我的测试中,所有表现出意想不到的低性能与超过1个连接的客户端。所讨论的服务器事件是尽可能快地发布到redis信道的1,000个消息,以尽可能快地分发。性能通过连接的客户端(socket.io-client,基于日志时间戳记到Redis列表进行分析)中的计时来衡量。

我推测在选项1中,服务器接收消息,然后顺序地将其写入所有连接的客户端。在选项2中,服务器多次接收每个消息(每个客户端预订一次),并将其写入相关的客户端。在任一种情况下,服务器不会得到第二个消息事件,直到它被传递到所有连接的客户端。随着并发性的提高,情况明显恶化。

这似乎与堆栈能力的感知智慧不一致。我想相信,但我在努力。

这种情况(大量消息的低延迟分布)不是这些工具的一个选项(还是?),或者我缺少一个招数?

解决方法

我认为这是一个合理的问题,并一直在研究它一会儿。我花了一些时间搜索例子,你可以从中提取一些有用的提示。

例子

我喜欢从直接的例子开始:

> light im sample code
> Node.js + Redis Pub/Sub + socket.io demo

光样是一个单页面(注意,你需要替换redis-node-client像node_redis由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,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',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");

文件

有很多文档,api在这种类型的堆栈上快速变化,所以你必须权衡每个文档的时间相关性。

> node activity streams
> cloud foundry example
> how to node redis pubsub
> redis latency
> redis cookbook Using Pub/Sub for Asynchronous Communication
> linkedin’s generic tips
> node redis bindings
> google groups nodejs question

相关问题

只是几个相关的问题,这是一个热门话题堆栈:

> Redis pub/sub for chat server in node.js
> How to design redis pub/sub for an instant messaging system?

值得注意的提示(ymmv)

关闭或优化套接字池,使用有效的绑定,监视延迟,并确保您不重复工作(即无需发布到所有侦听器两次)。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


这篇文章主要介绍“基于nodejs的ssh2怎么实现自动化部署”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“基于nodejs...
本文小编为大家详细介绍“nodejs怎么实现目录不存在自动创建”,内容详细,步骤清晰,细节处理妥当,希望这篇“nodejs怎么实现目录不存在自动创建”文章能帮助大...
这篇“如何把nodejs数据传到前端”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这...
本文小编为大家详细介绍“nodejs如何实现定时删除文件”,内容详细,步骤清晰,细节处理妥当,希望这篇“nodejs如何实现定时删除文件”文章能帮助大家解决疑惑...
这篇文章主要讲解了“nodejs安装模块卡住不动怎么解决”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来...
今天小编给大家分享一下如何检测nodejs有没有安装成功的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文...
本篇内容主要讲解“怎么安装Node.js的旧版本”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎...
这篇“node中的Express框架怎么安装使用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家...
这篇文章主要介绍“nodejs如何实现搜索引擎”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“nodejs如何实现搜索引擎...
这篇文章主要介绍“nodejs中间层如何设置”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“nodejs中间层如何设置”文...
这篇文章主要介绍“nodejs多线程怎么实现”,在日常操作中,相信很多人在nodejs多线程怎么实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法...
这篇文章主要讲解了“nodejs怎么分布式”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“nodejs怎么分布式”...
本篇内容介绍了“nodejs字符串怎么转换为数组”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情...
这篇文章主要介绍了nodejs如何运行在php服务器的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇nodejs如何运行在php服务器文章都...
本篇内容主要讲解“nodejs单线程如何处理事件”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“nodejs单线程如何...
这篇文章主要介绍“nodejs怎么安装ws模块”,在日常操作中,相信很多人在nodejs怎么安装ws模块问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法...
本篇内容介绍了“怎么打包nodejs代码”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!
本文小编为大家详细介绍“nodejs接收到的汉字乱码怎么解决”,内容详细,步骤清晰,细节处理妥当,希望这篇“nodejs接收到的汉字乱码怎么解决”文章能帮助大家解...
这篇“nodejs怎么同步删除文件”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇...
今天小编给大家分享一下nodejs怎么设置淘宝镜像的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希