Node.js、Socket.io、Redis发布/次高容量、低延迟困难
当结合socket.io/node.js和redis pub/sub试图创建一个由服务器事件驱动的实时web广播系统来处理多个传输时,似乎有三种方法:Node.js、Socket.io、Redis发布/次高容量、低延迟困难,node.js,redis,socket.io,publish-subscribe,low-latency,Node.js,Redis,Socket.io,Publish Subscribe,Low Latency,当结合socket.io/node.js和redis pub/sub试图创建一个由服务器事件驱动的实时web广播系统来处理多个传输时,似乎有三种方法: “createClient”创建redis连接并订阅频道。在socket.io客户端连接上,将客户端加入socket.io文件室。在redis.on(“message”,…)事件中,调用io.sockets.In(room).emit(“event”,data)以分发到相关文件室中的所有客户端。像 “createClient”是一个redis连接
这种情况(高容量消息的低延迟分发)是否不是这些工具的一种选择(目前?),还是我错过了一个窍门?我认为这是一个合理的问题,不久前对其进行了简要研究。我花了一点时间寻找一些例子,你可以从中获得一些有用的提示 例子 我喜欢从直截了当的例子开始:
/*
* 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");
/*
*迈凯轮酒吧:基于Redis的即时通讯
*Nikhil Marathe-22/04/2010
*一个使用
*Redis发布/订阅命令,以便所有通信
*已卸载到Redis,并且仅限于node.js代码
*处理命令解释、演示和订阅。
*
*需要redis节点客户端和最新版本的redis
* http://code.google.com/p/redis
* http://github.com/fictorial/redis-node-client
*
*启动服务器,然后远程登录到端口8000
*向NICK注册,使用WHO查看其他人
*使用TALKTO启动聊天。发送消息
*使用MSG.Note执行以下操作很重要
*交谈,以便双方都在倾听。使用“停止”
*停止与某人交谈,退出退出。
*
*此代码位于公共域中。
*/
var redis=require('./redis node client/lib/redis client');
var sys=需要('sys');
var net=要求的(‘净额’);
var server=net.createServer(函数(流){
var sub;//redis连接
var-pub;
var注册=假;
var nick=“”;
功能通道(a、b){
返回[a,b].sort().join(':');
}
功能共享表(其他){
系统调试(尼克+”:订阅“+频道(尼克,其他));
sub.subscribeTo(频道(尼克,其他)、功能(频道,消息){
var str=message.toString();
var sender=str.slice(0,str.indexOf(':');
如果(发送方!=尼克)
stream.write(“[”+sender+“]”“+str.substr(str.indexOf(“:”)+1)+“\n”);
});
}
功能表(其他){
sub.Unsubscribrom(频道(尼克、其他)、功能(错误){
stream.write(“停止与“+other+”\n)”交谈);
});
}
addListener(“连接”,函数(){
sub=redis.createClient();
pub=redis.createClient();
});
stream.addListener(“数据”),函数(数据){
如果(!已注册){
var msg=data.toString().match(/^NICK(\w*)/);
如果(味精){
stream.write(“服务器:Hi”+msg[1]+“\n”);
pub.sadd('mclarens:inside',msg[1],函数(err){
如果(错误){
stream.end();
}
注册=真实;
尼克=味精[1];
//服务器消息
sub.subscribeTo(尼克+“:信息”,函数(尼克,消息){
var m=message.toString().split(“”);
var cmd=m[0];
var-who=m[1];
如果(cmd==“开始”){
stream.write(who+“正在与您通话\n”);
可分享的(世卫组织);
}
否则如果(cmd==“停止”){
stream.write(谁+“停止与您交谈\n”);
可离职人员(世卫组织);
}
});
});
}
否则{
stream.write(“请向NICK注册”);
}
返回;
}
var fragments=data.toString().replace('\r\n','').split('');
开关(片段[0]){
“TALKTO”案例:
发布(片段[1]+“:info”,“start”+nick,函数(a,b){
});
可共享(片段[1]);
打破
案例“MSG”:
发布(频道(nick,fragments[1]),
尼克+':'+片段。切片(2)。连接(“”),
F