1

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

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

Client A 查询到 Client B 的 PID 和 NODE 后,Client A 和 B 就可以直接通信了。

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

4

1 回答 1

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/1andbinary_to_term/1在虚拟机内部的实际 pid 和二进制文件之间进行转换,您可以将其存储在任何接受二进制数据的地方,而不会以某种愚蠢的方式破坏它。

于 2011-06-12T18:33:15.677 回答