내 문제의 해결책. 별도의 프로세스에서 호출() :
나는 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) }.
아이디어는 모든 노드를 호출 한 제한 시간 내의 모든 결과를 기다리는 것입니다.
하나의 노드 호출은 생성 된 프로세스에서 수행됩니다. 오류가 발생한 경우 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.
단일 읽기는 시간 초과가있는 사서함에서 수신됩니다.
read(Timeout, Ref) ->
receive
{ Ref, Result } ->
{ ok, Result }
after Timeout ->
{ error, { read_timeout, Timeout } }
end.
또한 개선 :
- RPC 모듈 늦게 답변의 쓰레기를 피하기 위해 별도의 프로세스를 생성합니다. 그래서
infinity
이 타임 아웃이
봐 업데이트 된 대답에 확실한 방법으로 처리 할 수도 다중 호 기능에 동일한 작업을 수행하는 것이 유용 할 것이다 첫 번째 노드가 아닌 경우, 나는 그것이 솔루션에 문제 – Jr0