如何在socket.io中重用redis连接?

use*_*166 40 redis node.js socket.io

这是我的代码使用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();
    });
});
Run Code Online (Sandbox Code Playgroud)

每个新的io请求都将创建新的redis连接.如果有人用100个标签打开浏览器,那么redis客户端将打开100个连接.它看起来不太好看.

如果cookie相同,是否可以重用redis连接?因此,如果有人打开许多浏览器标签,也将其视为开放1连接.

sin*_*axi 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)
    })
  })

})
Run Code Online (Sandbox Code Playgroud)

  • 我知道这里的时间差距很大,但我相信这个问题的答案有些危险.每次新客户端加入聊天时,都会将事件侦听器绑定到sub的消息事件.客户端断开连接后,此事件侦听器将保留.这将导致过时的事件侦听器的堆积处理已经消失的客户端的消息. (20认同)
  • @Noli好问题.你会注意到,因为我们在套接字"连接"闭包中订阅了一个redis通道,所以只需要向每个人发送一个消息,因为子对象上的事件"消息"将被连接到每个连接的客户端.如果我们使用client.broadcast(),每个人都会看到该消息乘以房间内的人数. (4认同)
  • @Noli只是为了澄清,我们可以使用广播,但我们必须将侦听器绑定在"连接"闭包之外,以便事件只被触发一次.我们还必须将其更改为socket.broadcast(),因为我们无法使用客户端对象.根据具体情况,这可能会更好.接得好 :) (4认同)
  • @tabdulla我知道这个回复甚至更晚,但我已经想出如何解决悬空侦听器问题.http://stackoverflow.com/questions/11617811/how-to-remove-redis-on-message-listeners/11617812#11617812 (4认同)
  • 为了清楚起见,这只是创建了三个redis客户端,无论有多少用户连接.添加另一个节点进程显然会导致更多的redis客户端. (2认同)