Итак, во-первых, я создал микросервис, который загружает Football API, и через систему пабов / подсистем redis публикует любые изменения, если они есть, для livescores.
Теперь мой сервер с сокетами и маршрутами будет в кластерном режиме. Я уже настроил это с помощью socketio-redis. Вот фрагмент этой установки:
const io = require('socket.io')();
const sRedis = require('socket.io-redis');
const adapter = sRedis({ host: 'localhost', port: 6379 });
const { promisify } = require('util');
const Redis = require('ioredis');
const redis = new Redis();
redis.subscribe('livescore');
io.adapter(adapter);
const ioa = io.of('/').adapter;
ioa.clients = promisify(ioa.clients);
ioa.clientRooms = promisify(ioa.clientRooms);
ioa.remoteJoin = promisify(ioa.remoteJoin);
ioa.remoteLeave = promisify(ioa.remoteLeave);
ioa.allRooms = promisify(ioa.allRooms);
// notice this listener
redis.on('message', (channel, message) => {
io.emit('livescore', message);
})
io.on('connect', async (socket) => {
socket.clientRooms = () => ioa.clientRooms(socket.id);
socket.remoteJoin = (room) => ioa.remoteJoin(socket.id, room);
socket.remoteLeave = (room) => ioa.remoteLeave(socket.id, room);
socket.remoteDisconnect = () => ioa.remoteDisconnect(socket.id);
socket.on('join room', async (id) => {
await socket.remoteJoin(id);
socket.emit('join room', `You have joined room ${id}`)
socket.broadcast.emit('join room', `${socket.id} has joined.`)
});
socket.on('leave room', (id) => {
socket.remoteLeave(id);
});
})
module.exports = io;
Итак, если я запускаю один экземпляр этого узла приложения, все работает отлично.
Но если я запускаю его в режиме кластера, скажем, есть 4 кластера (я использую режим кластера с pm2), происходит следующее:
- Микросервис публикует событие.
- Каждый кластер имеет подписку на канале «livescore»
- Каждый кластер выполняет io.emit () (для всех клиентов)
- Клиент получает 4 одинаковых события почти одновременно.
Я выяснил, почему клиент получает 4 одинаковых события, но я хочу знать, как правильно справиться с этим?
Моя единственная мысль о решении состоит в том, что я делаю redis sub только для одного кластера и публикую все из этого, но я боюсь, что это будет слишком много работы для одного кластера?
Есть идеи?