[英]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.