Как повторно использовать подключение Redis в socket.io?
Вот мой код, использующий 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 ответов
На самом деле вы создаете новый клиент 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)
})
})
})
Redis оптимизирован для высокого уровня одновременных подключений. Также обсуждается несколько соединений с базой данных и реализация пула соединений в модуле node_redis.
Можно ли повторно использовать подключение Redis, если файлы cookie совпадают? Так что, если кто-то откроет много вкладок браузера, также будет считаться открытым 1 соединение.
Например, вы можете использовать хранилище HTML5 на стороне клиента, чтобы поддерживать активное подключение только к одной вкладке, а другие будут обрабатывать сообщения / сообщения через события хранилища. Это связано с этим вопросом.
Вы должны удалить слушателя, когда клиент отключается.
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.
У меня была именно эта проблема, с дополнительным требованием, что клиенты должны иметь возможность подписываться на частные каналы, и публикация на эти каналы не должна отправляться всем слушателям. Я попытался решить эту проблему, написав миниатюрный плагин. Плагин:
- Использует только 2 подключения Redis, один для паба, один для саба
- Подписывается на "сообщение" только один раз (не один раз за каждое соединение с Redis)
- Разрешить клиентам подписываться на свои собственные частные каналы без отправки сообщений всем остальным прослушивающим клиентам.
Особенно полезно, если ваш прототип находится в месте, где у вас есть ограничение на соединение Redis (например, Redis-To-Go). ТАК ссылка: /questions/39254668/chto-ya-dolzhen-ispolzovat-komnatyi-socketio-ili-pab-sab-redis/39254674#39254674
Использование Redis в качестве магазина стало намного проще, так как этот вопрос был задан / ответил. Он встроен сейчас.
Обратите внимание, что если вы используете Redis, потому что вы используете новые возможности кластеризации узлов (с использованием нескольких процессоров), вы должны создать сервер и подключить прослушиватели внутри каждого из вилок кластера (это никогда не объясняется нигде документация;)). Единственный хороший пример кода в Интернете, который я нашел, написан на CoffeeScript, и я вижу, что многие люди говорят, что этот тип вещей "просто не работает", и это определенно не так, если вы делаете это неправильно. Вот пример "сделать все правильно" (но это в CoffeeScript)