Как повторно использовать соединение redis в 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();
});
});
Каждый новый запрос io будет создавать новое соединение redis. Если кто-то откроет браузер с 100 вкладками, клиент redis откроет 100 подключений. Это не выглядит хорошо.
Можно ли повторно использовать соединение redis, если файлы cookie одинаковы?
Поэтому, если кто-то открывает многие вкладки браузера, также рассматривайте как открытое 1 соединение.
Ответы
Ответ 1
На самом деле вы создаете новый клиент 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)
})
})
})
Ответ 2
Redis оптимизирован для высокого уровня параллельных подключений. Существует также обсуждение о нескольких подключениях к базе данных и реализации пула соединений в node_redis.
Можно ли повторно использовать redis если файлы cookie одинаковы? Так если кто-то открывает много вкладок браузера обрабатывать как открытое 1 соединение.
Вы можете использовать, например, хранилище HTML5 на стороне клиента, чтобы активно подключаться только к одной вкладке, а другие будут обрабатывать сообщения/сообщения через хранилище Мероприятия. Это связано с этим вопросом.
Ответ 3
У меня была эта точная проблема, с дополнительным требованием, чтобы клиенты могли подписаться на частные каналы, а публикация этих каналов не должна быть отправлена всем слушателям. Я попытался решить эту проблему, написав миниатюрный плагин. Плагин:
- Использует только 2 соединения redis, один для pub, один для sub
- Только подписчивается на "сообщение" после полного (не один раз на повторное соединение)
- Разрешить клиентам подписываться на собственные частные каналы, без отправки сообщений всем другим слушающим клиентам.
Особенно полезно, если ваше прототипирование в месте, где у вас есть предел redis-соединения (например, redis-to-go).
Ссылка SO: fooobar.com/questions/8447/...
Ответ 4
Вам нужно удалить слушателя, когда клиент отключится.
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
Ответ 5
Использование redis в качестве магазина стало намного проще, так как этот вопрос задавался/отвечал. Теперь он встроен.
Обратите внимание, что если вы используете redis, потому что используете новые возможности кластеризации node (используя несколько процессоров), вам необходимо создать сервер и подключить слушателей внутри каждой из кластерных вилок (это никогда не происходит объясняется где угодно в любой документации;)). Единственный хороший пример кода, который я нашел, написан в CoffeeScript, и я вижу, что многие люди говорят, что этот тип вещей "просто не работает", и он определенно не делает, если вы делаете это неправильно. Вот пример "делать это правильно" (но это в CoffeeScript)