tl;博士:
在目标节点上生成一个进程来处理 RPC。
讨论
如果我们看一下 rpc 模块的代码,我们会发现它在 disterl 中封装了底层正常的节点间消息传递功能:
https://github.com/erlang/otp/blob/master/lib/kernel/src/rpc.erl#L398-L403
-spec cast(Node, Module, Function, Args) -> true when
Node :: node(),
Module :: module(),
Function :: atom(),
Args :: [term()].
cast(Node, Mod, Fun, Args) when Node =:= node() ->
catch spawn(Mod, Fun, Args),
true;
cast(Node, Mod, Fun, Args) ->
gen_server:cast({?NAME,Node}, {cast,Mod,Fun,Args,group_leader()}),
true.
发生的情况是,当在当前节点上调用 cast 时,会生成一个 新进程,并使用提供的 MFA 来执行。如果在不同的节点上调用案例,则通过gen_server:cast/2 向指定节点的组长发送一条消息,目标节点上的组长将生成一个处理 MFA 的进程。
演员的处理代码在这里:
https://github.com/erlang/otp/blob/master/lib/kernel/src/rpc.erl#L130-L139
-spec handle_cast(term(), state()) -> {'noreply', state()}.
handle_cast({cast, Mod, Fun, Args, Gleader}, S) ->
spawn(fun() ->
set_group_leader(Gleader),
apply(Mod, Fun, Args)
end),
{noreply, S};
handle_cast(_, S) ->
{noreply, S}. % Ignore !
如果您已经知道要将消息发送到另一个节点上的哪个进程,那么将节点的网格视为超级节点可能更有意义,绕过完全 rpc 模块,只需进行 gen_server 调用或直接对其进行转换。当然,使用哪种方法取决于品味和架构。