在线文档教程

分布式应用 | 9. Distributed Applications

9分布式应用

9.1 简介

在具有多个Erlang节点的分布式系统中,可能需要以分布式方式控制应用程序。如果运行某个应用程序的节点出现故障,则该应用程序将在另一个节点上重新启动。

这样的应用程序被称为分布式应用程序。请注意,它是分发的应用程序的控制。例如,所有应用程序都可以在其他节点上使用服务。

由于分布式应用程序可以在节点之间移动,所以需要一些寻址机制来确保它可以被其他应用程序解决,而不管它当前正在执行哪个节点。这个问题在这里没有解决,但是Kernel中的globalor pg2模块可以用于这个目的。

9.2指定分布式应用程序

分布式应用程序由应用程序控制器和分布式应用程序控制器进程控制dist_ac。这两个进程都是内核应用程序的一部分。通过使用以下配置参数(另请参阅kernel(6))配置内核应用程序来指定分布式应用程序:

distributed = [{Application, [Timeout,] NodeDesc}]

  • 指定应用程序Application = atom()可以执行的位置。

  • NodeDesc = [Node | {Node,...,Node}]是按优先级顺序排列的节点名称列表。元组中节点之间的顺序未定义。

  • Timeout = integer()指定在另一个节点上重新启动应用程序之前要等待多少毫秒。它默认为0。

为了使应用程序控制能够正常工作,分布式应用程序可以运行的节点必须相互联系并协商启动应用程序的位置。这是在内核中使用以下配置参数完成的:

  • sync_nodes_mandatory = [Node]- 指定必须启动哪些其他节点(在指定的超时范围内sync_nodes_timeout)。

  • sync_nodes_optional = [Node]- 指定可以启动哪些其他节点(在指定的超时范围内sync_nodes_timeout)。

  • sync_nodes_timeout = integer() | infinity - 指定等待其他节点启动的毫秒数。

启动时,节点等待由指定的所有节点sync_nodes_mandatory,并sync_nodes_optional就上来了。当所有节点都启动时,或者当所有强制节点都启动并且由时间指定的时间sync_nodes_timeout已过时,所有应用程序都会启动。如果不是所有强制节点都启动,则节点终止。

例子:

应用程序myapp将在节点上运行cp1@cave。如果此节点关闭,myapp则在cp2@cave或重新启动cp3@cave。系统配置文件cp1.configcp1@cave可以看看如下:

[{kernel, [{distributed, [{myapp, 5000, [cp1@cave, {cp2@cave, cp3@cave}]}]}, {sync_nodes_mandatory, [cp2@cave, cp3@cave]}, {sync_nodes_timeout, 5000} ] } ].

对于系统配置文件cp2@cavecp3@cave是相同的,除了强制节点的列表,这是要[cp1@cave, cp3@cave]cp2@cave[cp1@cave, cp2@cave]cp3@cave

注意

所有涉及的节点必须有相同的价值distributedsync_nodes_timeout。否则,系统行为未定义。

9.3 启动和停止分布式应用程序

当所有涉及的(强制性)节点都已启动时,可以通过application:start(Application)所有这些节点上调用来启动分布式应用程序

Releases可以使用引导脚本(请参阅)自动启动应用程序。

应用程序在distributed配置参数中的节点列表中列出的第一个操作节点处启动。应用程序像往常一样启动。也就是说,创建应用程序主文件并调用应用程序回调函数:

Module:start(normal, StartArgs)

例子:

继续上一节中的示例,启动三个节点,指定系统配置文件:

> erl -sname cp1 -config cp1 > erl -sname cp2 -config cp2 > erl -sname cp3 -config cp3

当所有节点都myapp可以运行时,可以启动。这是通过调用application:start(myapp)所有三个节点来实现的。然后开始cp1,如下图所示:

图9.1:应用程序myapp - 情况1

类似地,必须通过调用application:stop(Application)所有涉及的节点。

9.4故障转移

如果应用程序运行的节点出现故障,则在distributed配置参数中的节点列表中列出的第一个运行节点处重新启动应用程序(在指定的超时之后)。这称为故障转移

应用程序以新节点的正常方式启动,即由应用程序主服务器调用:

Module:start(normal, StartArgs)

如果应用程序start_phases定义了密钥(请参阅Included Applications),则是一个例外。然后,该应用程序通过调用来启动:

Module:start{failover, Node}, StartArgs)

这里Node是终止的节点。

例子:

如果cp1发生故障,系统将检查其中哪一个节点cp2cp3最少运行的应用程序数量,但要等待5秒钟cp1才能重新启动。如果cp1不重新启动并cp2运行更少的应用程序cp3myapp则重新启动cp2

图9.2:应用程序myapp - 情况2

假设现在cp2也下降并且在5秒内不重新启动。myapp现在重新启动cp3

图9.3:应用程序myapp - 情况3

9.5 接管

如果启动了一个节点,该节点根据distributed分布式应用程序运行的节点具有更高的优先级,则应用程序将在新节点处重新启动并停在旧节点处。这被称为接管

应用程序由应用程序主调用启动:

Module:start{takeover, Node}, StartArgs)

此处Node是旧节点。

实例:

如果myapp正在运行cp3,并且如果cp2现在重新启动,则它不会重新启动myapp,因为cp2cp3节点之间的顺序未定义。

图9.4:应用程序myapp-情景4

但是,如果cp1还重新启动,则该功能application:takeover/2myapp移至cp1,因为此cp1优先级高于cp3此应用程序。在这种情况下,Module:start{takeover, cp3@cave}, StartArgs)在执行时cp1启动应用程序。

图9.5:应用程序myapp-情景5