1

私は単純なスーパーバイザーを実装しようとしていますが、失敗した場合は子プロセスを再起動するだけです。しかし、スーパーバイザーの下で複数のプロセスを生成する方法さえ知りません! このサイトで簡単なスーパーバイザー コードを調べたところ、何かが見つかりました

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

init() 関数に「echo_server2」の部分を配置すると、このスーパーバイザーの下で別のプロセスが生成されると想定しましたが、例外 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}.
4

2 に答える 2

4

まず、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}
于 2011-12-01T03:52:43.263 に答える
2

同じサーバーの 2 つのインスタンスを実行するためだけに、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}ことです. すべてがどのように機能するかに従っています。

両方のサーバーを登録する場合は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]}]}}.

サーバーの登録名としてモジュール名を使用することは、サーバーの 1 つのインスタンスを実行する場合にのみ機能する規則です。

于 2011-12-06T15:49:55.120 に答える