我们使用分布式erlang集群,现在我在网络分裂的情况下测试它。
要从集群的所有节点获取信息,我使用gen_server:multicall / 4并定义了超时。我需要的是得到……
的 我解决了这个问题。 强>
我已经使用了自己的multicall实现 gen_server:call 基本思想是在单独的进程中使用gen_server:call()调用所有节点。并收集这些电话的结果。通过从调用进程的邮箱接收消息来进行收集。
gen_server:call
为了控制超时,我计算超时到期时的截止日期,然后将其用作参考点来计算超时 after 在 receive 。
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) ].
通过使用Timeout读取邮箱来收集结果
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.
只使用Timeout从邮箱接收一次读取。
read(Timeout, Ref) -> receive { Ref, Result } -> { ok, Result } after Timeout -> { error, { read_timeout, Timeout } } end.
进一步改进:
infinity