Как создать redis pub/sub для системы обмена мгновенными сообщениями?

Я новичок в redis pub/sub. У меня есть чат в системе, которая похожа на IM. Поэтому я хотел бы использовать redis pub/sub. Поскольку я рассмотрел образцы, большинство из них разработаны на основе чата. В моей системе у меня будет несколько чатов между пользователями, например:

A:B
A:C
D:C
E:F

Итак, строки выше - комнаты. И я реализовал сервер с node.js, как показано ниже;

var store = redis.createClient();
var pub = redis.createClient();
io.sockets.on('connection', function (socket) {
    var sub = redis.createClient();

    sub.on("message", function(pattern, data){
            data = JSON.parse(data);
        socket.send(JSON.stringify({ type: "chat", key: pattern, nick: data.nickname, message: data.text }))
        }
    });

    socket.on('message', function (messageData) {
        store.incr("messageNextId", function(e, messageId) {
        var room = ""
        var from = messageData.clientId > socket.nickname ? socket.nickname : messageData.clientId;
        var to = messageData.clientId < socket.nickname ? socket.nickname : messageData.clientId;   
            room = from + ":" + to;

        var message = { id: messageId, nickname: socket.nickname, text: messageData.text };
        store.rpush("rooms:" + room, JSON.stringify(message), function(e, r) {  
             pub.publish(room, JSON.stringify(message))
        });
    });
});

Как вы можете видеть, я создаю нового абонента redis для каждого подключения. В других чатах выборки клиент-клиент redis создается глобально. И существует только три соединения все время, и это решает их проблему, потому что, когда издатель публикует сообщение, все подключенные клиенты должны его получить. Но у меня есть ограничение. Я хочу открыть сеанс чата между двумя пользователями, и только эти пользователи должны быть подписчиками. Код выше работает так, как хотелось бы, но я не знаю, нормально ли для redis создавать новый клиент-подписчик для каждого соединения.

Было бы здорово услышать ваши предложения. Заранее спасибо.

Ответ 1

Как всегда, вам нужно сравнивать такие вещи, как это для вашего собственного случая использования - невозможно дать общие рекомендации. Возможно, вам потребуется увеличить максимальное количество открытых файлов в вашей системе, как в общесистемной, так и для пользователя redis. Это также относится к пользователю, который запускает ваш веб-сервер, конечно.

Тем не менее, вы должны обязательно слушать socket.on('disconnect') и quit() абонента redis, когда пользователь уходит. Вам также может быть интересно узнать, что у socket.io есть redis-сервер, который использует redis pub/sub, а также имеет концепцию комнат, поэтому вы можете сэкономить себе некоторую проблему, используя это, поскольку вы уже зависите от сокета .io.

Изменить: После быстрой проверки я получаю это сообщение об ошибке от Redis после 991 подписчика:

Ready check failed: Error: Error: ERR max number of clients reached

Вот от значения по умолчанию redis.conf:

# Set the max number of connected clients at the same time. By default
# this limit is set to 10000 clients, however if the Redis server is not
# able ot configure the process file limit to allow for the specified limit
# the max number of allowed clients is set to the current file limit
# minus 32 (as Redis reserves a few file descriptors for internal uses).
#
# Once the limit is reached Redis will close all the new connections sending
# an error 'max number of clients reached'.
#
# maxclients 10000

Моя система (Ubuntu 11.11) имеет ограничение по умолчанию nofile, равное 1024, поэтому мой быстрый тест должен завершиться неудачно после 992 подключенных клиентов, что, кажется, прямо из теста (у меня также есть один клиент для издателя). Мое предложение для вас - проверить свой предел nofile (в моей системе он находится в /etc/security/limits.{conf,d/*} и настройке redis maxclients, а затем в контрольном, эталонном, эталоном!