私の問題の解決策。私はgen_server:call
基本的な考え方を使用してマルチコールの私の独自の実装を作った
はgen_serverですべてのノードを呼び出すことです:別のプロセスで()を呼び出します。これらの呼び出しの結果を収集します。収集は、呼び出しプロセスのメールボックスからメッセージを受信することによって行われます。
タイムアウトを制御するには、タイムアウトが期限切れになったときの期限を計算し、それを参照ポイントとして使用してafter
のタイムアウトをreceive
に計算します。
実装
主な機能は次のとおりです。ここ
multicall(Nodes, Name, Req, Timeout) ->
Refs = lists:map(fun(Node) -> call_node(Node, Name, Req, Timeout) end, Nodes),
Results = read_all(Timeout, Refs),
PosResults = [ { Node, Result } || { ok, { ok, { Node, Result } } } <- Results ],
{ PosResults, calc_bad_nodes(Nodes, PosResults) }.
アイデアは、すべてのノードを呼び出し、1つのタイムアウト内の全ての結果を待つことです。
1ノードの呼び出しは、生成されたプロセスから実行されます。エラーの場合はgen_server:call
で使用されている出口をキャッチします。締め切りは
を発生しなくなるまで
call_node(Node, Name, Req, Timeout) ->
Ref = make_ref(),
Self = self(),
spawn_link(fun() ->
try
Result = gen_server:call({Name,Node},Req,Timeout),
Self ! { Ref, { ok, { Node, Result } } }
catch
exit:Exit ->
Self ! { Ref, { error, { 'EXIT', Exit } } }
end
end),
Ref.
バート・ノードがタイムアウトしてメールボックスを読み取ることによって、TIMOUT
calc_bad_nodes(Nodes, PosResults) ->
{ GoodNodes, _ } = lists:unzip(PosResults),
[ BadNode || BadNode <- Nodes, not lists:member(BadNode, GoodNodes) ].
結果内に応答されていないものを収集しているように計算されている
read_all(ReadList, Timeout) ->
Now = erlang:monotonic_time(millisecond),
Deadline = Now + Timeout,
read_all_impl(ReadList, Deadline, []).
実装読み取り
read_all_impl([], _, Results) ->
lists:reverse(Results);
read_all_impl([ W | Rest ], expired, Results) ->
R = read(0, W),
read_all_impl(Rest, expired, [R | Results ]);
read_all_impl([ W | Rest ] = L, Deadline, Results) ->
Now = erlang:monotonic_time(millisecond),
case Deadline - Now of
Timeout when Timeout > 0 ->
R = read(Timeout, W),
case R of
{ ok, _ } ->
read_all_impl(Rest, Deadline, [ R | Results ]);
{ error, { read_timeout, _ } } ->
read_all_impl(Rest, expired, [ R | Results ])
end;
Timeout when Timeout =< 0 ->
read_all_impl(L, expired, Results)
end.
1回の読み取りは、タイムアウトのあるメールボックスからの受信だけです。
read(Timeout, Ref) ->
receive
{ Ref, Result } ->
{ ok, Result }
after Timeout ->
{ error, { read_timeout, Timeout } }
end.
さらなる改良:
- RPCモジュールは、後半の答えのゴミを避けるために別のプロセスを生成します。だから、
infinity
はタイムアウトが
ルック更新回答で明らかな方法で処理することができる。このマルチコール機能で同じことを行うことが有用であろう最初のノードではない場合、私はそれはあなたのソリューションでは、あなたの問題 – Jr0