我正在使用Erlang为多人桌面游戏构建一个小型网络服务器。 此网络服务器使用Mnesia DB的本地实例为每个连接的客户端应用程序存储会话。在存储在本地Mnesia中的每个客户端记录(会话)内,我存储客户端的PID和NODE(客户端登录的节点)。
我计划在至少2台连接的服务器(节点A和B)上部署此网络服务器。 因此,为了允许在节点A上登录的客户端A搜索(向Mnesia查询)在节点B上登录的客户端B,我将Mnesia会话表从节点A复制到节点B或反之亦然
客户端A查询客户端B的PID和NODE后,客户端A和B可以直接相互通信。
这是在两个不同的Erlang节点上登录的两个客户端应用程序之间建立连接的正确方法吗?
答案 0 :(得分:3)
根据定义,创建一个两个或多个节点完全同步的系统是不可能的。然而,在实践中,您可能已经足够接近它可以解决您的特定问题。
你没有说明在两个节点上运行的确切原因,所以我将假设它是为了可扩展性。对于许多节点,如果您正确使用,您的系统也将更具可用性和容错性。但是,如果您知道自己只在单个节点中运行,并且需要另一个节点作为热备用服务器来接管主节点不可用,则可以简化问题。
要在两个不同节点上的两个进程之间建立连接,您需要一些全局寻址(用户ID 123是pid< 123,456,0>)。如果您还关心一次只运行一个用户A的进程,则还需要锁定或仅允许唯一的寻址注册。如果您还想增长,则需要一种方法来添加更多节点,无论是在系统运行时还是在系统停止时。
现在,已经有一些解决方案有助于解决您的问题,并有不同的权衡:
全局模式下的gproc,允许在给定键下注册进程(它为您提供寻址和锁定)。这被分发到整个集群,没有单点故障,但是领导者选举(至少在我上次查看它时)仅适用于系统启动时可用的节点。添加新节点需要gen_leader的实验版本或停止系统。在你自己的代码中,如果你知道两个玩家只会相互交谈,你可以在同一个节点上启动它们。
riak_core,允许您构建在riak KV和riak搜索中使用的经过充分测试和验证的架构之上。它以一种允许您添加新节点并重新分配密钥的方式将密钥映射到存储桶。您可以插入此机制并移动您的流程。这种方法不允许您决定从哪里开始您的流程,因此如果您之间有很多沟通,这将通过网络进行。
将mnesia与分布式事务一起使用,可以保证每个节点在提交事务之前都有数据,这样可以分发寻址和锁定,但是你必须在其他方面做其他事情。这(就像释放锁)。注意:我从未在生产中使用分布式事务,因此我无法告诉您它们的可靠性。此外,由于分发,预计延迟。注意2:您应该确切地检查如何添加更多节点并复制表格,例如,如果可以在不停止mnesia的情况下进行复制。
Zookeper / doozer / roll自己的,提供了一个集中的高可用性数据库,您可以使用它来存储寻址。在这种情况下,您需要自己处理取消注册。从寻址的角度来看,在系统运行时添加节点很容易,但是您需要某种方法让应用程序了解新节点并在那里开始生成进程。
此外,没有必要存储节点,因为pid包含足够的信息以将消息直接发送到正确的节点。
作为您可能已经知道的一个很酷的技巧,可以将pid序列化(可能是 VM中的所有数据)到二进制文件。使用term_to_binary/1
和binary_to_term/1
在VM内部的实际pid和二进制文件之间进行转换,您可以将其存储在任何接受的二进制数据中,而不会以某种愚蠢的方式对其进行修改。