我有一个独特的问题,无需在elxir中解决。
我需要使用动态管理器来在群集环境中动态启动(n)个孩子。我正在使用libcluster来管理集群,并使用全局进程注册表来查找动态主管pid。这是正在发生的事情:
global: Name conflict terminating {:packer_supervisor, #PID<31555.1430.0>}
以下是主管的代码:
defmodule EcompackingCore.PackerSupervisor do
use DynamicSupervisor
require Logger
def start_link() do
DynamicSupervisor.start_link(__MODULE__, :ok, name: {:global, :packer_supervisor})
end
def init(:ok) do
Logger.info("Starting Packer Supervisor")
DynamicSupervisor.init(strategy: :one_for_one)
end
def add_packer(badge_id, packer_name) do
child_spec = {EcompackingCore.Packer, {badge_id, packer_name}}
DynamicSupervisor.start_child(:global.whereis_name(:packer_supervisor), child_spec)
end
def remove_packer(packer_pid) do
DynamicSupervisor.terminate_child(:global.whereis_name(:packer_supervisor), packer_pid)
end
def children do
DynamicSupervisor.which_children(:global.whereis_name(:packer_supervisor))
end
def count_children do
DynamicSupervisor.count_children(:global.whereis_name(:packer_supervisor))
end
end
问题似乎是在两个节点上都启动了主管。处理此问题的最佳方法是什么?我确实需要主管保持动态,以便我可以有效地管理工作程序模块。可能是其他注册表?
感谢您的帮助。
答案 0 :(得分:2)
经过一番研究,我找到了解决方案:
我现在正在使用https://github.com/bitwalker/swarm处理pid注册。这允许跨集群设置流程,并在其中一个节点发生故障时提供切换支持。
答案 1 :(得分:1)
您可以使用一个简单的中央节点来监视其他节点,当然是一个主管。
此中央节点仅启动monitor,并使用数据库保存其他节点的状态和pid。
当节点连接和断开时,您可以接收其断开消息并进行处理(更新数据库)。
此方法的唯一缺点是您只能有一个中央节点,但是由于该节点做简单的事情,它几乎是稳定的,可以在我们的生产系统上运行一年。
答案 2 :(得分:1)
如果您希望使用与全局流程注册表一起使用的简单解决方案,则可以更改动态主管start_link
let str = "hello world" returns [5, 5]
关于此解决方案的很多人会说,您不应该这样做,因为在网络分裂的情况下,您最终会在集群中遇到两个或多个全局进程。但是,如果您实现一些节点监视/跟踪器,甚至知道在集群中“看到”了多少个节点,您甚至可以解决这个问题。
例如,如果集群大小为iz 5,那么您可以创建检查规则,该规则将检查是否看到3个以上的节点,如果没有,则您将在下一个1秒内安排下一次启动,然后尝试在全局范围内重新注册动态主管直到检查规则返回true(表示您属于多数组,并且可以在该组中提供一致性)。另一方面,如果您的节点是少数群体,并且已经拥有全局动态主管,则将其关闭,并计划在1秒内开始。
这是在整个群集中实现一致性的最简单方法,但是您应该考虑一件事。该动态监控器将在单个节点上启动工作程序,我敢肯定您不会这样做,因此可以使用全局注册表和一些负载平衡算法来平衡应在本地监控器中启动的进程。