【问题标题】:Erlang: Spawn more than one process under a supervisorErlang:在主管下产生多个进程
【发布时间】:2012-01-10 06:50:22
【问题描述】:

我正在尝试实现一个简单的主管,并在子进程失败时让它重新启动它们。但是,我什至不知道如何在主管下生成多个进程!我在这个网站上查看了简单的主管代码,发现了一些东西

-module(echo_sup).
-behaviour(supervisor).
-export([start_link/0]).
-export([init/1]).

start_link() ->
    {ok, Pid} = supervisor:start_link(echo_sup, []),
    unlink(Pid).
init(_Args) ->
    {ok,  {{one_for_one, 5, 60},
       [{echo_server, {echo_server, start_link, []},
         permanent, brutal_kill, worker, [echo_server]},

        {echo_server2, {echo_server2, start_link, []},
         permanent, brutal_kill, worker, [echo_server2]}]}}.

我认为将“echo_server2”部分放在 init() 函数中会在该主管下生成另一个进程,但我最终收到异常退出:关闭消息。

文件“echo_server”和“echo_server2”代码相同,但名称不同。所以我现在很困惑。

-module(echo_server2).
-behaviour(gen_server).

-export([start_link/0]).
-export([echo/1, crash/0]).
-export([init/1, handle_call/3, handle_cast/2]).

start_link() ->
    {ok,Pid} = gen_server:start_link({local, echo_server2}, echo_server2, [], []),
    unlink(Pid).

%% public api
echo(Text) ->
    gen_server:call(echo_server2, {echo, Text}).
crash() ->
    gen_server:call(echo_server2, crash).

%% behaviours
init(_Args) ->
    {ok, none}.
handle_call(crash, _From, State) ->
    X=1,
    {reply, X=2, State};
handle_call({echo, Text}, _From, State) ->
    {reply, Text, State}.
handle_cast(_, State) ->
    {noreply, State}.

【问题讨论】:

    标签: erlang erlang-supervisor gen-server


    【解决方案1】:

    首先,您需要阅读一些关于 OTP/gen_server 和 OTP/supervisors 的文档。您的代码中几乎没有错误。

    1) 在 echo_sup 模块中改变你的 start_link 函数如下:

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

    不知道你为什么在进程启动后unlink/1

    2) 在两个 echo_servers 中将 start_link 函数更改为:

    start_link() -> 
        gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).
    

    你不应该改变这个函数的返回值,因为主管期望这个值之一:

    {ok,Pid} | ignore | {error,Error}
    

    【讨论】:

      【解决方案2】:

      您不需要两个不同的模块来运行同一服务器的两个实例。冲突问题是由于子规范中的标签必须是唯一的。它是元组中的第一个元素。所以你可以有类似的东西:

          [{echo_server, {echo_server, start_link, []},
            permanent, brutal_kill, worker, [echo_server]},
           {echo_server2, {echo_server, start_link, []},
            permanent, brutal_kill, worker, [echo_server]}]}}.
      

      为什么要取消子进程的链接?主管使用这些链接来监督其子项。您得到的错误是主管希望启动子项的函数返回{ok,ChildPid},这就是它获取子项的pid的方式,因此当它获得另一个返回值时,子项的启动失败,然后给出自己起来。一切都按照它应该如何工作。

      如果您想注册两个服务器,那么您可以修改start_link 函数以将名称用作参数并传递,以便您可以通过子规范显式传递它。所以:

      start_link(Name) -> 
          gen_server:start_link({local, Name}, ?MODULE, [], []).
      

          [{echo_server, {echo_server, start_link, [echo_server]},
            permanent, brutal_kill, worker, [echo_server]},
           {echo_server2, {echo_server, start_link, [echo_server2]},
            permanent, brutal_kill, worker, [echo_server]}]}}.
      

      使用模块名称作为服务器的注册名称只是一种约定,仅当您运行服务器的一个实例时才有效。

      【讨论】:

        猜你喜欢
        • 2012-04-06
        • 2014-11-29
        • 1970-01-01
        • 2015-08-22
        • 1970-01-01
        • 2011-10-06
        • 2010-10-08
        • 2013-11-22
        • 1970-01-01
        相关资源
        最近更新 更多