这是为多客户端应用构建Erlang网络服务器的正确方法吗?

这是为多客户端应用构建Erlang网络服务器的正确方法吗?,erlang,multiplayer,mnesia,Erlang,Multiplayer,Mnesia,我正在使用Erlang为多人棋盘游戏构建一个小型网络服务器。 此网络服务器使用Mnesia DB的本地实例为每个连接的客户端应用程序存储会话。在本地Mnesia中存储的每个客户机记录(会话)中,我存储客户机的PID和节点(客户机登录的节点) 我计划在至少两个连接的服务器(节点A和B)上部署此网络服务器。 因此,为了允许登录节点a的客户端a搜索(查询到Mnesia)登录节点B的客户端B,我将Mnesia会话表从节点a复制到节点B,反之亦然 客户端A查询客户端B的PID和节点后,客户端A和客户端B可

我正在使用Erlang为多人棋盘游戏构建一个小型网络服务器。 此网络服务器使用Mnesia DB的本地实例为每个连接的客户端应用程序存储会话。在本地Mnesia中存储的每个客户机记录(会话)中,我存储客户机的PID和节点(客户机登录的节点)

我计划在至少两个连接的服务器(节点A和B)上部署此网络服务器。 因此,为了允许登录节点a的客户端a搜索(查询到Mnesia)登录节点B的客户端B,我将Mnesia会话表从节点a复制到节点B,反之亦然

客户端A查询客户端B的PID和节点后,客户端A和客户端B可以直接通信


这是在登录到两个不同Erlang节点的两个客户端应用程序之间建立连接的正确方法吗?

根据定义,创建两个或多个节点完全同步的系统是不可能的。然而,在实践中,您可能离得足够近,以至于它可以解决您的特定问题

您没有说在两个节点上运行的确切原因,所以我假设这是为了可伸缩性。由于有许多节点,如果您做对了,您的系统也将更加可用和容错。但是,如果您知道您只会在单个节点中运行,并且在主节点不可用时需要另一个节点作为热从节点来接管,则问题可能会简化

要在两个不同节点上的两个进程之间建立连接,需要一些全局寻址(用户id 123是pid)。若您还关心一次只为一个正在运行的用户运行一个进程,那个么您还需要一个锁或只允许唯一的地址注册。如果还希望增长,则需要在系统运行或停止时添加更多节点

现在,已经有一些解决方案可以帮助解决您的问题,有不同的权衡:

  • gproc在全局模式下,允许在给定密钥下注册进程(这将提供寻址和锁定)。这是分布到整个集群的,没有单点故障,但是领导者选举(至少在我上次看到它时)只对系统启动时可用的节点有效。添加新节点需要实验版本的gen_leader或停止系统。在您自己的代码中,如果您知道两个玩家只会彼此交谈,那么您可以在同一节点上启动他们

  • riak_core允许您在riak KV和riak search中使用的经过良好测试和验证的体系结构之上构建。它以允许您添加新节点并重新分配密钥的方式将密钥映射到存储桶中。您可以插入此机制并移动流程。这种方法不允许您决定从何处开始流程,因此,如果您在流程之间有很多沟通,这将通过网络进行

  • 在分布式事务中使用mnesia,可以保证在提交事务之前每个节点都有数据,这将为您分配寻址和锁定,但您必须在这之上执行所有其他操作(如释放锁)。注意:我从未在生产中使用过分布式事务,所以我无法告诉您它们有多可靠。此外,由于是分布式的,因此需要等待时间。注2:您应该准确地检查如何添加更多节点并复制表,例如,如果不停止mnesia就可以

  • Zookeper/doozer/roll your own提供了一个集中的高可用数据库,您可以使用该数据库存储地址。在这种情况下,您需要自己处理注销。从寻址的角度来看,在系统运行时添加节点很容易,但是您需要一些方法让应用程序了解新节点并在那里开始生成进程

此外,不需要存储节点,因为pid包含足够的信息,可以将消息直接发送到正确的节点


您可能已经知道了一个很酷的技巧,可以将PID(以及VM中的所有数据)序列化为二进制文件。使用
term_to_binary/1
binary_to_term/1
在虚拟机内的实际pid和二进制文件之间进行转换,您可以将其存储在任何接受二进制数据的文件中,而不会以某种愚蠢的方式将其损坏。

感谢您的解释Knutin:)。。。您可能会猜到我对Erlang(6个月)很陌生。如果您对我的答案感到满意,您应该将其标记为“已接受”。我注意到你问了其他问题,这些问题也得到了回答,但你没有将最佳答案标记为已接受。请务必这样标记,因为StackOverflow就是这样工作的。对不起。。。但“接受”按钮在哪里?对不起,我真的刚从你那里知道。。。谢谢