我怎么处理插座?IO和集群的房间吗?

时间:2022-08-22 15:47:56

I have a server working with cluster and to make that work with socke.IO I am using sticky-session, but I have a problem with my rooms (I don't know if the way I did is the best option): The cluster is instantiating processes and each process has a specific number of rooms.

我有一个服务器和集群一起工作,让它和socke一起工作。IO我正在使用sticky会话,但是我的房间有一个问题(我不知道我这样做是不是最好的选择):集群正在实例化进程,每个进程都有特定数量的房间。

  • Server
    • Process 1
      • Room1
      • Room1
      • Room2
      • Room2
      • Room N
      • 房间N
    • 1房2房N
    • Process 2
      • Room1
      • Room1
      • Room2
      • Room2
      • Room N
      • 房间N
    • 过程2房间1房间2房间N
  • 服务器进程1房2房N进程2房2房N

The way I did to connect some user to the rooms (with only one process) is using the route, where the user access a page and when he tries to make a connection with Socket.io I check the URL and with that information I insert him in a room.

我将一些用户连接到房间(只有一个进程)的方法是使用路由,用户访问一个页面并尝试与Socket建立连接。我检查一下网址,然后把他放在房间里。

My problem is implementing this server with cluster I can not insert the user in specific rooms because there is some rooms that only exist in specific processes and sticky session put him in another process. How can I put an user in a room that is in another process ? Also The use can only to see the routes of the process he is in the server and I would like to show every rooms in the page.

我的问题是用集群实现这个服务器,我不能将用户插入到特定的房间中,因为有些房间只存在于特定的进程中,而粘性会话将用户放置在另一个进程中。如何将用户放在另一个进程中的房间?另外,只能查看服务器中进程的路由,我想显示页面中的每个房间。

I already has read about Redis-Adapter but I didn't find solutions on github using Socket.io + Cluster(Sticky-session + redis-adapter) + rooms.

我已经读过关于Redis-Adapter的文章,但是我没有找到使用Socket在github上的解决方案。io +集群(Sticky-session + redis-adapter) +房间。

Follow my code to share what I have done:

按照我的代码分享我所做的:

//Cluster.Master with simplified Code
if (cluster.isMaster) {

   var workers = [];
   // Spawn workers.
   for (var i = 0; i < num_processes; i++) {
      spawn(i);
   }

   // Create the outside facing server listening on our port.
   var server = net.createServer({
        pauseOnConnect: true
   }, function(connection) {
        // We received a connection and need to pass it to the appropriate
        // worker. Get the worker for this connection's source IP and pass
       // it the connection.
       var worker = workers[worker_index(connection.remoteAddress, num_processes)];
       worker.send('sticky-session:connection', connection);
   }).listen(process.env.PORT);
} else {
     console.log('I am worker #' + cluster.worker.id);
     var app = new express();

     //view engine
     app.set('views', './views');
     app.set('view engine', 'pug');
     //statics
     app.use(express.static(path.join(__dirname, 'public')));
     //rooms
     app.use('/', rooms);
     var server = app.listen(0, 'localhost'),
         io = sio(server);
     io.adapter(sio_redis({ host: 'localhost', port: 6379 }));

    //This File has the socket events (socket.on('messageX', function(){}))
    // And there I am 
    var realtime = require('./realtime/socketIOEvents.js')(io);

    // Listen to messages sent from the master. Ignore everything else.
    process.on('message', function(message, connection) {
    if (message !== 'sticky-session:connection') {
        return;
    }
   // Emulate a connection event on the server by emitting the
   // event with the connection the master sent us.
   server.emit('connection', connection);
   connection.resume();
});
}

3 个解决方案

#1


2  

socketio-redis is a right thing to do. Every sserver/process listens to a topic in redis queue. To understand in short socketio-redis just publishes the event to every other server/process in cluster. So as far as the Rooms are concern they are just an abstraction to a group of sockets interested in listening to messages in the room.

索科蒂奥-雷迪斯是正确的选择。每个sserver/进程在redis队列中侦听一个主题。要理解的是,socketio-redis只是将事件发布到集群中的其他所有服务器/进程中。就房间而言,它们只是一组对在房间里听消息感兴趣的套接字的抽象。

Even if sockets are distributed to different servers/processes they can be a part of same room. As every message comes in, every server knows about it and passes on the to required sockets.

即使套接字分布到不同的服务器/进程,它们也可以是同一个房间的一部分。当每个消息传入时,每个服务器都知道它并传递到所需的套接字。

As far as correctness is concern, Your architecture is right also correct as your proxy decides also selectively forwards the message but it is increasing hops in a lifecycle of a message. You really do not need this proxy to handle socket routing.

就正确性而言,您的体系结构也是正确的,因为您的代理决定也有选择地转发消息,但这增加了消息生命周期中的跳数。您确实不需要这个代理来处理套接字路由。

#2


1  

Here is the example code which will worked based on the room joining with.

下面是基于房间连接的示例代码。

http://www.html5gamedevs.com/topic/12321-create-a-cluster-server-with-nodejs-and-socketio/

http://www.html5gamedevs.com/topic/12321-create-a-cluster-server-with-nodejs-and-socketio/

Let me know if you have question in this post.

如果你在这篇文章中有问题,请告诉我。

#3


1  

After a lot of tries I did this with a Proxy server in the top of the workers and every workers registering rooms in another server (Redis). When I connect to the server with the URL of a room, my proxy server detects which worker I am trying to connect and route my web socket connection to the right worker.

在多次尝试之后,我在工作人员的顶部使用了一个代理服务器,并且每个工作人员都在另一个服务器(Redis)中注册了房间。当我用一个房间的URL连接到服务器时,我的代理服务器检测我正在连接哪个worker,并将我的web套接字连接路由到正确的worker。

                      Proxy
           /            |          \
worker(5rooms)   worker(5rooms)  worker(5rooms)
           \            |          /
                      Redis

That solves my problem but it is not using socket.io-redis. How can we solve that problem with socket.io-redis? Add every users, sockets and variables in redis to make just the processing in the workers is a valid approach ?

这解决了我的问题,但它不是使用socketl .io-redis。我们如何用足球来解决这个问题?在redis中添加每个用户、套接字和变量,以使处理工作成为有效的方法?

#1


2  

socketio-redis is a right thing to do. Every sserver/process listens to a topic in redis queue. To understand in short socketio-redis just publishes the event to every other server/process in cluster. So as far as the Rooms are concern they are just an abstraction to a group of sockets interested in listening to messages in the room.

索科蒂奥-雷迪斯是正确的选择。每个sserver/进程在redis队列中侦听一个主题。要理解的是,socketio-redis只是将事件发布到集群中的其他所有服务器/进程中。就房间而言,它们只是一组对在房间里听消息感兴趣的套接字的抽象。

Even if sockets are distributed to different servers/processes they can be a part of same room. As every message comes in, every server knows about it and passes on the to required sockets.

即使套接字分布到不同的服务器/进程,它们也可以是同一个房间的一部分。当每个消息传入时,每个服务器都知道它并传递到所需的套接字。

As far as correctness is concern, Your architecture is right also correct as your proxy decides also selectively forwards the message but it is increasing hops in a lifecycle of a message. You really do not need this proxy to handle socket routing.

就正确性而言,您的体系结构也是正确的,因为您的代理决定也有选择地转发消息,但这增加了消息生命周期中的跳数。您确实不需要这个代理来处理套接字路由。

#2


1  

Here is the example code which will worked based on the room joining with.

下面是基于房间连接的示例代码。

http://www.html5gamedevs.com/topic/12321-create-a-cluster-server-with-nodejs-and-socketio/

http://www.html5gamedevs.com/topic/12321-create-a-cluster-server-with-nodejs-and-socketio/

Let me know if you have question in this post.

如果你在这篇文章中有问题,请告诉我。

#3


1  

After a lot of tries I did this with a Proxy server in the top of the workers and every workers registering rooms in another server (Redis). When I connect to the server with the URL of a room, my proxy server detects which worker I am trying to connect and route my web socket connection to the right worker.

在多次尝试之后,我在工作人员的顶部使用了一个代理服务器,并且每个工作人员都在另一个服务器(Redis)中注册了房间。当我用一个房间的URL连接到服务器时,我的代理服务器检测我正在连接哪个worker,并将我的web套接字连接路由到正确的worker。

                      Proxy
           /            |          \
worker(5rooms)   worker(5rooms)  worker(5rooms)
           \            |          /
                      Redis

That solves my problem but it is not using socket.io-redis. How can we solve that problem with socket.io-redis? Add every users, sockets and variables in redis to make just the processing in the workers is a valid approach ?

这解决了我的问题,但它不是使用socketl .io-redis。我们如何用足球来解决这个问题?在redis中添加每个用户、套接字和变量,以使处理工作成为有效的方法?