如何在erlang中的Supervisor行为下启动同一模块/功能的多个实例?

时间:2013-07-21 19:04:38

标签: erlang

拥有模块/功能 mymodule ,如何在supervisor行为下多次启动它?

我需要同时启动相同进程(mymodule)的2个实例。我将子标识符称为 child1 child2 。它们都指向我想要启动的 mymodule 模块。我已经指定了两个不同的函数来启动工作进程“mymodule”(start_link1和start_link2)的每个实例

-module(my_supervisor).

-behaviour(supervisor).

-export([start_link/0, init/1]).

start_link() ->
    supervisor:start_link({local, ?MODULE}, ?MODULE, _Arg = []).

init([]) ->
    {ok, {{one_for_one, 10, 10},
          [{child1,
            {mymodule, start_link1, []},
            permanent,
            10000,
            worker,
            [mymodule]}
          ,
           {child2,
            {mymodule, start_link2, []},
            permanent,
            10000,
            worker,
            [mymodule]}
          ]}}.

worker 有两个不同的start_link函数(start_link1和start_link2)用于测试目的:

-module(mymodule).
-behaviour(gen_server).

start_link1() ->
    log_something("at link 1"),
    gen_server:start_link({global, child1}, ?MODULE, [], []).

start_link2() ->
    log_something("at link 2"),
    gen_server:start_link({global, child2}, ?MODULE, [], []).

init([]) ->
    ....

通过上面我可以在我的日志中看到消息“在链接1”,但它确实在任何地方显示“在链接2”。它也没有在link1的实例中执行任何操作:显然已经死了。

唯一有效的方案是名称“child1”匹配工作模块名称“mymodule”。

3 个答案:

答案 0 :(得分:1)

查看supervisor:start_link()的文档。您在此处传递的第一个参数是用于向global注册的名称,该名称提供全局name -> pid查找。由于这必须是唯一的,因此您的第二个进程无法启动,因为该名称已被占用。

修改:这是指向文档的链接:http://erldocs.com/R15B/stdlib/supervisor.html?i=5&search=supervisor:start#start_link/3

答案 1 :(得分:1)

同时检查simple-one-for-one主管重启方案。它允许以更自动化的方式启动具有相同子规范的多个进程。

答案 2 :(得分:1)

正如@MilleBessö要求您尝试两个具有相同注册名称的进程? mymodule:start_link是否以固定名称注册mymodule进程?如果是这样,那么尝试开始第二次将导致冲突。你试图启动多个my_supervisor主管吗?然后你也会得到一个名字冲突。您尚未包含my_module的代码。

请记住,您只能在名称下注册一个进程。这适用于本地注册的进程和使用global注册的进程。

编辑:主管是否也会死?

gen_server回调完成并返回正确的值(init)之前,不会认为{ok,State}和所有其他行为都已正确启动。因此,如果mymodule:init/1中出现错误,那么这会导致子进程崩溃,然后初始化并且主管将放弃。虽然主管可以并且将在孩子死后重新启动,但确实要求他们都正确启动。来自supervisor:start_link/3

  

如果成功创建了主管及其子进程(即,如果所有子进程启动函数都返回{ok,Child},{ok,Child,Info}或忽略),则该函数返回{ok,Pid},其中Pid是主管的pid。如果已存在具有指定SupName的进程,则该函数返回{error,{already_started,Pid}},其中Pid是该进程的pid。

     

如果Module:init / 1返回ignore,则此函数也返回ignore,并且主管终止,原因正常。如果Module:init / 1失败或返回不正确的值,则此函数返回{error,Term},其中Term是一个包含错误信息的术语,并且主管终止,原因是Term。

我不知道这是否是问题所在,但它会产生与你相同的行为。