簡體   English   中英

Erlang:在主管的領導下進行多個流程

[英]Erlang: Spawn more than one process under a supervisor

我正在嘗試實現一個簡單的主管,並讓它在失敗時重新啟動子進程。 但是,我什至不知道如何在主管下生成多個進程! 我在這個網站上查看了簡單的主管代碼,發現了一些東西

-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()函數中將在此管理程序下生成另一個進程,但最終導致出現異常exit:shutdown消息。

文件“ 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}.

首先,您需要閱讀一些有關OTP / gen_server和OTP / supervisor的文檔。 您的代碼中幾乎沒有錯誤。

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}

您不需要兩個不同的模塊即可運行同一服務器的兩個實例。 沖突問題是由於子規范中的標簽必須唯一。 它是元組中的第一個元素。 因此,您可能會遇到以下情況:

    [{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]}]}}.

使用模塊名稱作為服務器的注冊名稱只是一種約定,只有在您運行服務器的一個實例時才有效。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM