Erlang:单身人士的最佳途径
设置:
我想在erlang集群中启动一个独特的全局注册gen_server进程。 如果进程停止或节点正在运行,则该进程将在其他节点之一上启动。
该过程是主管的一部分。 问题在于启动第二个节点上的管理引擎失败,因为gen_server已经在运行并从第一个节点全局注册。
问题(S):
{ok, Pid}
而不是启动一个新的gen_server实例? global:trans()
吗? 示例代码:
start_link() ->
global:trans({?MODULE, ?MODULE}, fun() ->
case gen_server:start_link({global, ?MODULE}, ?MODULE, [], []) of
{ok, Pid} ->
{ok, Pid};
{error, {already_started, Pid}} ->
link(Pid),
{ok, Pid};
Else -> Else
end
end).
将gen_server转变为应用程序并使用分布式应用程序如何?
如果你返回{ok,Pid}你没有链接的东西会混淆依赖返回值的管理员。 如果你不想要一个主管将它用作start_link函数,你可以避开它。
您的方法似乎应该起作用,因为如果全局节点死亡,每个节点都会尝试启动一个新的实例。 您可能会发现您需要在管理员设置中增加MaxR
值,因为每当群集成员更改时您都会收到处理消息。
我过去创建全局单例的一种方法是在所有节点上运行该进程,但其中一个(获得全局注册竞赛的人)成为主节点。 其他进程监视主服务器,当主服务器退出时,尝试成为主服务器。 (再次,如果他们没有赢得注册竞赛,那么他们会监控所做的那个)。 如果你这样做,你必须自己处理全局名称注册(即不要使用gen_server:start({global, ...
functionality),因为无论它是否赢得注册,您都希望该过程开始,它会只是在每种情况下表现不同。
这个过程本身必须更加复杂(它必须在主模式和非主模式下运行),但它很快稳定下来,并且不会在管理员启动尝试时产生大量日志垃圾邮件。
我的方法通常需要进行几轮修改来摆脱角落的情况,但是在我看来,编写OTP分布式应用程序的麻烦比较少。 与分布式应用程序相比,此方法具有另一个优点,即您无需静态配置集群中涉及的节点列表 - 任何节点都可以成为运行进程主副本的候选项。 你的方法有这个相同的属性。
链接地址: http://www.djcxy.com/p/38217.html上一篇: Erlang: Best way for a singleton gen
下一篇: How to reference previously started processes in an Elixir supervisor