Как создать 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
, а затем в контрольном, эталонном, эталоном!