这是我的代码,使用socket.io作为WebSocket,后端使用pub / sub redis。
var io = io.listen(server),
buffer = [];
var redis = require("redis");
var subscribe = redis.createClient(); **<--- open new connection overhead**
io.on('connection', function(client) {
console.log(client.request.headers.cookie);
subscribe.get("..", function (err, replies) {
});
subscribe.on("message",function(channel,message) {
var msg = { message: [client.sessionId, message] };
buffer.push(msg);
if (buffer.length > 15) buffer.shift();
client.send(msg);
});
client.on('message', function(message){
});
client.on('disconnect', function(){
subscribe.quit();
});
});
每个新的io请求都会创建新的redis连接。如果有人用100个标签打开浏览器,那么redis客户端将打开100个连接。它看起来不太好。
如果cookie相同,是否可以重用redis连接? 因此,如果有人打开许多浏览器标签,也将其视为开放1连接。
答案 0 :(得分:60)
实际上,如果要在“连接”事件上实例化客户端,则只为每个连接创建一个新的redis客户端。创建聊天系统时我更喜欢创建三个redis客户端。一个用于发布,订阅,一个用于将值存储到redis中。
例如:
var socketio = require("socket.io")
var redis = require("redis")
// redis clients
var store = redis.createClient()
var pub = redis.createClient()
var sub = redis.createClient()
// ... application paths go here
var socket = socketio.listen(app)
sub.subscribe("chat")
socket.on("connection", function(client){
client.send("welcome!")
client.on("message", function(text){
store.incr("messageNextId", function(e, id){
store.hmset("messages:" + id, { uid: client.sessionId, text: text }, function(e, r){
pub.publish("chat", "messages:" + id)
})
})
})
client.on("disconnect", function(){
client.broadcast(client.sessionId + " disconnected")
})
sub.on("message", function(pattern, key){
store.hgetall(key, function(e, obj){
client.send(obj.uid + ": " + obj.text)
})
})
})
答案 1 :(得分:2)
Redis是optimized for a high level of concurrent connections。关于discussion模块中的多个数据库连接和连接池实现,还有node_redis。
是否可以重复使用redis 如果cookie是相同的连接?所以 如果有人打开许多浏览器标签 视为开放1连接。
您可以在客户端使用例如HTML5 storage来保持仅主动连接一个选项卡,而其他人将通过存储事件处理通信/消息。这与this问题有关。
答案 2 :(得分:1)
我遇到了这个问题,并且要求客户端必须能够订阅私有频道,并且不应将发布到这些频道发送给所有侦听器。我试图通过编写一个微型插件来解决这个问题。插件:
如果您在具有redis连接限制的地方进行原型设计(例如redis-to-go),则特别有用。 SO链接:https://stackoverflow.com/a/16770510/685404
答案 3 :(得分:1)
您需要在客户端断开连接时删除侦听器。
var io = io.listen(server),
buffer = [];
var redis = require("redis");
var subscribe = redis.createClient();
io.on('connection', function(client) {
console.log(client.request.headers.cookie);
subscribe.get("..", function (err, replies) {
});
var redis_handler = function(channel,message) {
var msg = { message: [client.sessionId, message] };
buffer.push(msg);
if (buffer.length > 15) buffer.shift();
client.send(msg);
};
subscribe.on("message", redis_handler);
client.on('message', function(message){
});
client.on('disconnect', function(){
subscribe.removeListerner('message', redis_handler)
//subscribe.quit();
});
});
请参阅Redis, Node.js, and Socket.io : Cross server authentication and node.js understanding
答案 4 :(得分:0)
使用redis作为商店变得更加简单,因为这个问题被提出/回答了。 It is built in now
请注意,如果您使用的是redis,因为您正在使用新节点群集功能(使用多个CPU),则必须创建服务器并将侦听器附加到每个群集分支中(这在任何地方都不会实际解释)在任何文件中;))。我发现的唯一优秀的在线代码示例是用CoffeeScript编写的,我看到很多人说这种类型的东西“只是不起作用”,如果你做错了肯定不会 。 Here's an example of "doing it right" (but it is in CoffeeScript)