【问题标题】:New connection cause the current connections to stop working新连接导致当前连接停止工作
【发布时间】:2020-11-22 22:15:33
【问题描述】:

我正在使用具有多个租户结构并使用命名空间的套接字(我是新手)制作聊天应用程序。这是我的代码:

套接字服务器: index.js

class Server {
    constructor() {
        this.port = process.env.PORT || 3000;
        this.host = process.env.HOST || `localhost`;

        this.app = express();
        this.http = http.Server(this.app);
        this.rootSocket = socketio(this.http);
    }

    run() {
        new socketEvents(this.rootSocket).socketConfig();
        this.app.use(express.static(__dirname + '/uploads'));
        this.http.listen(this.port, this.host, () => {
            console.log(`Listening on ${this.host}:${this.port}`);
        });
    }
}

const app = new Server();
app.run();

socket.js

var redis = require('redis');
var redisConnection = {
    host: process.env.REDIS_HOST,
    password: process.env.REDIS_PASS
};
var sub = redis.createClient(redisConnection);
var pub = redis.createClient(redisConnection);

class Socket {

    constructor(rootSocket) {
        this.rootIo = rootSocket;
    }

    socketEvents() {

        /**
         * Subscribe redis channel
         */
        sub.subscribe('visitorBehaviorApiResponse');
        //TODO: subscribe channel..

        // Listen to redis channel that published from api
        sub.on('message', (channel, data) => {
            data = JSON.parse(data);
            console.log(data);
            const io = this.rootIo.of(data.namespace);
            if (channel === 'visitorBehaviorApiResponse') {
                io.to(data.thread_id).emit('receiveBehavior', data);
                io.to('staff_room').emit('incomingBehavior', data);
            }
        })

        sub.on('error', function (error) {
            console.log('ERROR ' + error)
        })

        var clients = 0;
        this.rootIo.on('connection', (rootSocket) => {
            clients++;
            console.log('root:' + rootSocket.id + ' connected (total ' + clients + ' clients connected)');
            const ns = rootSocket.handshake['query'].namespace;

            // Dynamic namespace for multiple tenants
            if (typeof (ns) === 'string') {
                const splitedUrl = ns.split("/");
                const namespace = splitedUrl[splitedUrl.length - 1];
                const nsio = this.rootIo.of(namespace);
                this.io = nsio;

                this.io.once('connection', (socket) => {
                    var visitors = [];

                    console.log('new ' + socket.id + ' connected');

                    // once a client has connected, we expect to get a ping from them saying what room they want to join
                    socket.on('createChatRoom', function (data) {
                        socket.join(data.thread_id);
                        if (typeof data.is_staff !== 'undefined' && data.is_staff == 1) {
                            socket.join('staff_room');
                        } else {
                            if (visitors.some(e => e.visitor_id === data.visitor_id)) {
                                visitors.forEach(function (visitor) {
                                    if (visitor.visitor_id === data.visitor_id) {
                                        visitor.socket_ids.push(socket.id);
                                    }
                                })
                            } else {
                                data.socket_ids = [];
                                data.socket_ids.push(socket.id);
                                visitors.push(data);
                            }
                            socket.join('visitor_room');
                        }

                        //TODO: push to redis to check conversation type

                    });

                    socket.on('sendMessage', function (data) {
                        console.log(data);
                        pub.publish('chatMessage', JSON.stringify(data));
                        this.io.in(data.thread_id).emit('receiveMessage', data);
                        this.io.in('staff_room').emit('incomingMessage', data);
                        // Notify new message in room
                        data.notify_type = 'default';
                        socket.to(data.thread_id).emit('receiveNotify', data);
                    }.bind(this))

                    socket.on('disconnect', (reason) => {
                        sub.quit();
                        console.log('client ' + socket.id + ' left, ' + reason);
                    });

                    socket.on('error', (error) => {
                        console.log(error);
                    });

                });
            }

            // Root disconnect
            rootSocket.on('disconnect', function () {
               clients--;
               console.log('root:' + rootSocket.id + ' disconnected (total ' + clients + ' clients connected)');
            });
        });
    }

    socketConfig() {
        this.socketEvents();
    }
}
module.exports = Socket;

客户:

    const server = 'https://socket-server'
    const connect = function (namespace) {
        return io.connect(namespace, {
           query: 'namespace=' + namespace,
           resource: 'socket.io',
           transports: ['websocket'],
           upgrade: false
        })
    }
    const url_string = window.location.href
    const url = new URL(url_string)
    const parameters = Object.fromEntries(url.searchParams)
    const socket = connect(`${server}/${parameters.shopify_domain}`)
    var handleErrors = (err) => {
      console.error(err);
    }
    
    socket.on('connect_error', err => handleErrors(err))
    socket.on('connect_failed', err => handleErrors(err))
    socket.on('disconnect', err => handleErrors(err))

我遇到的问题是,当套接字服务器获得新连接时,现有连接将停止工作,直到它们刷新页面以重新连接新的 socket.id。

当命名空间的客户端发出数据时,它会发送到其他命名空间,似乎我的代码在命名空间中无法正常工作。

你能看看我的代码并指出我哪里错了吗?

谢谢

【问题讨论】:

    标签: node.js sockets redis socket.io


    【解决方案1】:
    1) Get UserId or accessToken while handshaking(in case of accessToken decrypt it).
     and store userID: socketId(in Redis or in local hashmap) depends upon the requirement .
    
    2) When u are going to emit to particular user fetch the  socketid to that userid from redis or local hashmap
    and emit to it.
    
    
    **io.to(socketId).emit('hey', 'I just met you');**
    
    
    3) If you are using multiple servers use sticky sessions
     
    4) Hope this will help you
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-24
      • 2021-03-20
      相关资源
      最近更新 更多