Как повторно использовать подключение Redis в socket.io? - PullRequest
40 голосов
/ 21 апреля 2011

Вот мой код, использующий socket.io в качестве WebSocket и backend с 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 подключений. Это не выглядит красиво.

Можно ли повторно использовать подключение redis, если файлы cookie совпадают? Так что, если кто-то откроет много вкладок браузера, также будет считаться открытым 1 соединение.

Ответы [ 5 ]

60 голосов
/ 22 апреля 2011

На самом деле вы создаете новый клиент redis для каждого соединения, только если вы создаете экземпляр клиента в событии "connection" При создании системы чата я предпочитаю создавать три клиента 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)
    })
  })

})
2 голосов
/ 21 апреля 2011

Redis оптимизирован для для высокого уровня одновременных подключений . Также обсуждение о множественных соединениях с базой данных и реализации пула соединений в модуле node_redis .

Можно ли повторно использовать Redis соединение, если куки совпадают? Так если кто-то также откроет много вкладок браузера рассматривать как открытое 1 соединение.

Вы можете использовать, например, Хранилище HTML5 на стороне клиента, чтобы поддерживать активное подключение только к одной вкладке, а другие будут обрабатывать сообщения / сообщения через события хранения. Это связано с этим вопросом.

1 голос
/ 14 февраля 2014

Необходимо отключить прослушиватель при отключении клиента.

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 и Socket.io: межсерверная аутентификация и понимание node.js

1 голос
/ 07 июня 2013

У меня была именно эта проблема, с дополнительным требованием, чтобы клиенты могли иметь возможность подписываться на частные каналы, и публикация на эти каналы не должна отправляться всем слушателям. Я попытался решить эту проблему, написав миниатюрный плагин. Плагин:

  • Использует только 2 подключения Redis, одно для паба, одно для саба
  • Подписывается на «сообщение» только один раз (не один раз за каждое соединение redis)
  • Разрешить клиентам подписываться на свои частные каналы без отправки сообщений всем остальным прослушивающим клиентам.

Особенно полезно, если ваш прототип находится в месте, где у вас есть ограничение на соединение redis (например, redis-to-go). ТАК ссылка: https://stackoverflow.com/a/16770510/685404

0 голосов
/ 05 августа 2013

Использование redis в качестве магазина стало намного проще, поскольку этот вопрос был задан / получен ответ. Встроено сейчас .

Обратите внимание, что если вы используете Redis, потому что вы используете новые возможности кластеризации узлов (с использованием нескольких процессоров), вы должны создать сервер и подключить прослушиватели внутри каждой из вилок кластера (это нигде не объясняется в любой документации;)). Единственный хороший пример кода в Интернете, который я нашел, написан на CoffeeScript, и я вижу, что многие люди говорят, что этот тип вещей "просто не работает", и это определенно не , если вы делаете это неправильно . Вот пример "сделать все правильно" (но это в CoffeeScript)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...