Concurrency 什么进程执行rpc:cast?

Concurrency 什么进程执行rpc:cast?,concurrency,erlang,Concurrency,Erlang,现在,我正在构建一个分布式应用程序,并正在研究使用rpc:cast vs rpc:call,因为我不希望调用进程等待返回值,甚至不希望接收返回值 Cast在这方面非常有效,但我很好奇,是什么进程执行rpc:Cast和call传递的函数?我应该担心过度/不足并发吗 通常,当我需要另一个进程执行代码时,我会使用一个worker池,使用gen_server:cast/2向其中一个进程发送一个异步cast,并让它们处理它。但是对于RPC,它没有定义什么进程进行计算。流程是否预先分配并等待?还是每个进程都

现在,我正在构建一个分布式应用程序,并正在研究使用rpc:cast vs rpc:call,因为我不希望调用进程等待返回值,甚至不希望接收返回值

Cast在这方面非常有效,但我很好奇,是什么进程执行rpc:Cast和call传递的函数?我应该担心过度/不足并发吗

通常,当我需要另一个进程执行代码时,我会使用一个worker池,使用gen_server:cast/2向其中一个进程发送一个异步cast,并让它们处理它。但是对于RPC,它没有定义什么进程进行计算。流程是否预先分配并等待?还是每个进程都是在rpc调用时生成的,然后终止?从我所读到的,这是难以置信的效率低下,如果你是作出许多呼吁,因为进程只是被创建和销毁,这是不容易计算


提前感谢您的帮助

tl;医生:

在目标节点上生成的处理RPC的进程

讨论

如果我们看一下rpc模块的代码,就会发现它在disterl中封装了底层的正常节点间消息传递功能:

这里发生的事情是,当在当前节点上调用cast时,将生成一个新进程,其中包含要执行的所提供的MFA。如果在不同的节点上调用case,则会通过
gen_server:cast/2
向指定节点的组长发送一条消息,并且目标节点上的组长将生成一个处理MFA的进程

演员阵容的处理代码如下:


如果您已经知道要向另一个节点上的哪个进程发送消息,那么将节点网格视为超级节点可能更有意义,完全绕过rpc模块,只需进行gen_服务器调用或直接向其强制转换。当然,使用哪种方法取决于品味和架构。

过程的名称是
rex
。它是一个已注册的进程,生成一个执行
apply(M,F,a)
的进程


顺便说一句,这意味着所有的
rpc:call/4
rpc:cast/4
以及其他参数都要经过一个过程,这限制了可伸缩性
rpc
模块不用于高吞吐量目的。

它们通过
rex
进行pas,但是
rex
产生一个单独的工作程序来实际执行每个作业,除非发送一个
调用块(然后
rex
执行自己的)。是的,你是对的
rex
生成一个真正工作的流程。我编辑了答案。因为在Erlang中生成速度非常快,我认为最大的性能瓶颈是人们在disterl上发送大小消息时会遇到的差异。如果rpc调用的参数以字节为单位非常大,则可能会出现奇怪的行为。或者,如果连接速度慢或延迟高。RPC变得非常复杂,但我认为生成部分是所有开销中最小的(大约8微秒,网络延迟将远高于此)。因此发送大量RPC通信可能不是一个好主意,因为每次node1从node2接收RPC,它必须派生出一个全新的进程,我已经读到这是一个密集型进程。您建议另一种方法,获取关于节点的预定义信息并将其发送到gen_server:cast()-理想情况下,尽管您希望使用一个池,以便1)不会派生新进程(时间问题)2)如果消息涌入,则并发性受到限制。那么您如何知道进程id呢?如果要获得进程id,您必须首先从node2咨询node1上某种形式的grpoc_get_worker?是否有任何普遍接受的解决方法,或者这是一种“修复”,每个人都有不同的做法?@Ryan事实上,我有好消息要告诉你!Erlang中的派生进程在时间、内存和CPU方面都非常轻量级。与另一个节点通信所涉及的网络通信和延迟比rex所做的工作要昂贵得多。因此,即使在另一端只有一个
rex
,您也可以毫不费力地对请求进行垃圾邮件处理,
rex
的工作开销可以忽略不计。如果您有非常复杂的计算,而RPC非常适合,那么强制转换的成本是您开销中考虑最少的。@Ryan至于“替代方案”,您可以直接在另一个节点上生成进程,这就是为什么
spawn/2
spawn/4
接受
节点
参数()。所有这些都不可能在不知道作业是什么、负载是什么等的情况下做出正确的判断。操作的上下文就是一切。无论您在做什么,编写一些测试用例来查看它们对负载的反应应该非常简单。你可以来和我们讨论一下。非常感谢。你可以看出我对所有这些过程都有顾虑,但这似乎不是什么大不了的事。我不记得在哪里读到过erlang中进程的开销很高,但现在我很高兴知道这不是一个大问题。谢谢你的帮助!
-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.
-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 !