简体   繁体   English

如何处理带有集群的Socket.IO房间?

[英]How can I Handle Socket.IO rooms with cluster?

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工作我正在使用粘性会话,但我的房间有问题(我不知道我的方式是否是最好的选择):集群实例化流程,每个流程都有特定数量的房间。

  • Server 服务器
    • Process 1 过程1
      • Room1 会议室1
      • Room2 室2
      • Room N N室
    • Process 2 过程2
      • Room1 会议室1
      • Room2 室2
      • Room N 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.io建立连接时,我检查URL并使用该信息插入他在一个房间里。

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.io + Cluster(Sticky-session + redis-adapter)+ rooms的github上找到解决方案。

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();
});
}

socketio-redis is a right thing to do. socketio-redis是一件正确的事情。 Every sserver/process listens to a topic in redis queue. 每个sserver /进程都会侦听redis队列中的主题。 To understand in short socketio-redis just publishes the event to every other server/process in cluster. 要简单了解socketio-redis,只需将事件发布到集群中的每个其他服务器/进程。 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. 因此,就房间而言,它们只是对一组有兴趣听取房间信息的插座的抽象。

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. 您真的不需要此代理来处理套接字路由。

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. 如果您对此帖有疑问,请与我们联系。

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). 经过大量尝试后,我在工作人员的顶部使用代理服务器,并在另一台服务器(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. 当我使用房间的URL连接到服务器时,我的代理服务器会检测我尝试连接的工作人员并将我的Web套接字连接路由到正确的工作人员。

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

That solves my problem but it is not using socket.io-redis . 这解决了我的问题,但它没有使用socket.io-redis How can we solve that problem with socket.io-redis? 我们如何用socket.io-redis解决这个问题? Add every users, sockets and variables in redis to make just the processing in the workers is a valid approach ? 在redis中添加每个用户,套接字和变量,只是在worker中处理是一种有效的方法吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM