首页 > 解决方案 > 带有 Socket.IO 和命名空间的 NodeJs-Cluster

问题描述

我正在构建一个浏览器游戏。原型已经完成,现在我正在考虑如何扩展和托管它。我已经有一个“游戏服务器”,它目前处理一个游戏会话。一个游戏会话由一个到 8 个玩家(最多)的 socketio 连接组成。

我想使用例如Node-Cluster在同一个 docker-container 中有多个“游戏服务器”,其中每个游戏服务器应该处理一个或多个游戏会话,以便可以使用 cpu 的所有内核。一个游戏会话仅由 8 个玩家使用,游戏会话应彼此隔离。

据我所知,Node-Cluster 使我能够让所有子进程共享同一个端口。我想为每个游戏会话设置一个名称空间(例如,玩家无论如何都连接到的浏览器中的 ID - 目标是:您获得一个发送给朋友以邀请他的 URL,类似于例如 skribble.io - https://localhost/?gameid=1234)。所以就我而言,加入命名空间基本上与加入游戏相同。

我的目标是拥有多个这些 docker-containers,并使用反向代理将传入连接路由到正确的容器,该容器处理游戏,在 url 中指定。但这里的问题是,我不知道如何将连接转发到集群的正确子进程。

所以最后它应该如下所示:

 GameServerMaster [Maps ids to processes like: [ClusterNode1:[id1,id2,..]}
   - GameServerClusterNode1
     - GameSession1 [id1 io.off("/id1")]
     - GameSession2 [id2 io.off("/id2)]
     - ....
   - GameServerClusterNode2
     - GameSession3 [id3 io.off("/id3")]
     - GameSession4 [id4 io.off("/id4)]
     - ....

我找到了socket.io-redis,但这似乎有点过分了,因为没有广播 - 每个游戏都是孤立的。(而且我不想只为这个用例托管redis)

另外,我找到了sticky-session,但是通过使用它我不知道如何将传入的连接转发到正确的进程,我认为它只是对它们进行负载平衡,这很糟糕,因为它必须路由到那个实际上处理请求的游戏会话-但我认为无论如何我都需要类似的东西,或者我是吗?

我正在做的(或计划做的)是正确的方法吗?您在技术或架构方面有什么建议吗?

扔掉整个集群部分,只让 docker-container 处理一个“节点”来处理这些多个游戏会话会更好吗?

标签: javascriptnode.jssocket.ionode-cluster

解决方案


我发现自己处于同样的情况,并提出了以下解决方案。

主意:

您使用不同端口上的集群模块创建新进程。使用主进程,您就像路由器一样。

例子:

在玩家加入房间之前,他询问路由器,
(广播)123房间在哪里。路由器询问他的子进程
它们中的哪一个托管房间 123,并转发结果(例如端口 3001)
 给客户。然后客户端连接到确切的进程。

问题:

如果多个子进程有相同的roomId,就会发生冲突,
但我想你会想办法避免这种情况,
即使发生这种情况的可能性非常低。

需要注意的是,这个解决方案是使用你机器的所有内核,而不是分发到多台机器的解决方案。

如果你想将它分发到多台机器上,你应该重新考虑 Redis 作为你的首选。


推荐阅读