1

モジュール/関数mymoduleがあり、スーパーバイザーの動作の下で複数回起動する方法は?

たとえば、同じプロセス(mymodule) の 2 つのインスタンスを同時に開始する必要があります。子識別子をchild1およびchild2と呼びました。どちらも、開始したいmymoduleモジュールを指しています。ワーカー プロセス「mymodule」の各インスタンスを開始する 2 つの異なる関数を指定しました ( 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]}
          ]}}.

ワーカーには、テスト目的で 2 つの異なる 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 」と一致する場合です。

4

3 に答える 3

1

@MilleBessöが尋ねるように、同じ登録名を持つ2つのプロセスを試みていますか? mymodulemymodule:start_linkプロセスを固定名で登録しますか? その場合、2 つ目を開始しようとすると衝突が発生します。複数のmy_supervisorスーパーバイザーを起動しようとしていますか? その後、名前の衝突も発生します。のコードが含まれていませんmy_module

1 つの名前で登録できるプロセスは 1 つだけであることを忘れないでください。これは、ローカルに登録されたプロセスと を使用して登録されたプロセスの両方に当てはまりますglobal

編集:スーパーバイザーも死ぬのですか?

Aおよび他のすべての動作は、コールバックが完了して正しい値を返すgen_serverまで、適切に開始されたと見なされません( )。そのため、エラーが発生すると、初期化されるに子プロセスがクラッシュし、スーパーバイザーはあきらめます。スーパーバイザーは、子供が死亡したときに子供を再起動することができ、また再起動しますが、すべての子供が正しく起動する必要があります。スーパーバイザーから:start_link/3init{ok,State}mymodule:init/1

スーパーバイザとその子プロセスが正常に作成された場合 (つまり、すべての子プロセス開始関数が {ok,Child}、{ok,Child,Info}、または無視を返す場合)、関数は {ok,Pid} を返します。Pid は pid です。スーパーバイザーの。指定された SupName を持つプロセスが既に存在する場合、関数は {error,{already_started,Pid}} を返します。Pid はそのプロセスの pid です。

Module:init/1 が無視を返す場合、この関数は無視も返し、スーパバイザは通常の理由で終了します。Module:init/1 が失敗するか、正しくない値を返す場合、この関数は {error,Term} を返します。ここで、Term はエラーに関する情報を含む用語であり、スーパーバイザーは理由 Term で終了します。

これが問題かどうかはわかりませんが、同じ動作をします。

于 2013-07-23T00:14:23.620 に答える
1

シンプルな 1 対 1 のスーパーバイザ再起動シナリオも確認してください。より自動化された方法で、同じ子仕様で複数のプロセスを開始できます。

于 2013-07-22T09:40:55.373 に答える
1

のドキュメントを確認してくださいsupervisor:start_link()。ここで渡す最初のパラメータglobalは、グローバルname -> pidルックアップを提供する に登録するために使用する名前です。これは一意でなければならないため、名前が既に使用されているため、2 番目のプロセスは開始できません。

編集: ドキュメントへのリンクは次のとおりです: http://erldocs.com/R15B/stdlib/supervisor.html?i=5&search=supervisor:start#start_link/3

于 2013-07-21T19:57:38.477 に答える