现在,假设我们正在设计一个应用程序,由 2 个 Erlang 节点组成。在节点 A 上,将有非常多的进程,数量级为数千。这些进程通过向节点 B 上的已注册进程发送消息来访问节点 B 上的资源。在节点 B,假设您通过执行以下函数启动了一个进程:
start_server()->
register(zeemq_server,spawn(?MODULE,server,[])),ok.<br>
server()->
receive
{{CallerPid, Ref}, {Module, Func, Args}} ->
Result = (catch erlang:apply(Module, Func, Args)),
CallerPid ! {Ref, Result},
server();
_ -> server()
end.
在节点 A 上,任何想要在节点 B 上执行给定模块中的任何功能的进程都使用以下代码:call(Node, Module, Func, Args)->
Ref = make_ref(),
Me = self(),
{zeemq_server,Node} ! {{Me, Ref}, {Module, Func, Args}},
receive
{Ref, Result} -> Result
after timer:minutes(3) ->
error_logger:error_report(["Call to server took so long"]),
{error,remote_call_failed}
end.
所以假设 Process zeemq_server
在 Node B 上,永远不会 down,并且 Node A 和 B 之间的网络连接总是 up,请回答以下问题:Qn 1:由于Node B上只有一个接收进程,它的邮箱很可能一直是满的。这是因为,节点 A 上的进程很多,并且在给定的时间间隔内,例如 2 秒,每个进程至少对节点 B 服务器进行一次调用。可以通过哪些方式使节点 B 上的接收变得冗余? ,例如进程组等并解释(概念)这将如何替换上面的服务器端代码。显示客户端会发生什么变化。
Qn 2:在节点 B 上只有一个接收者的情况下,进程邮箱中允许的最大消息数是多少?如果单个进程邮件牛被太多消息淹没,erlang 将如何响应?
Qn 3:使用上面显示的概念,我可以通过什么方式保证每个发送请求的进程在超时发生之前尽快得到答案?将节点 B 上的接收部分转换为并行操作有帮助吗?像这样:
start_server()->
register(zeemq_server,spawn(?MODULE,server,[])),ok.<br>
server()->
receive
{{CallerPid, Ref}, {Module, Func, Args}} ->
<b>spawn(?MODULE,child,[Ref,CallerPid,{Module, Func, Args}]),</b>
server();
_ -> server()
end.
child(Ref,CallerPid,{Module, Func, Args})->
Result = (catch erlang:apply(Module, Func, Args)),
CallerPid ! {Ref, Result},
ok.
如上所示的方法,可能会增加Node B上运行的瞬时进程数,这可能会因内存的原因而对服务造成很大影响。但是,它看起来不错,使 server()
循环立即返回以处理下一个请求。您对此修改有何看法?最后:说明如何实现
Pool of receiver Threads
在节点 B 上,但似乎低于 Name
关于节点 A。这样,传入消息在接收线程之间多路复用,并且在这组进程中共享负载。保持问题的含义相同。
最佳答案
进程邮箱中的最大消息数不受限制,内存量除外。
此外,如果您需要检查邮箱大小,请使用
erlang:process_info(self(),[message_queue_len,messages]).
这将返回如下内容:
[{message_queue_len,0},{messages,[]}]
我建议您首先将上面的服务器转换为 gen_server。这是你的 worker 。
接下来,我建议使用 poolboy (https://github.com/devinus/poolboy) 作为 poolboy 工作人员创建一个服务器实例池(在他们的 github Readme.md 中有示例)。最后,我建议使用辅助方法为调用者创建一个模块,该方法创建一个 poolboy 事务并将池中的 Worker arg 应用于函数。以下示例来自他们的 github:
squery(PoolName, Sql) ->
poolboy:transaction(PoolName, fun(Worker) ->
gen_server:call(Worker, {squery, Sql})
end).
也就是说,Erlang RPC 会更好地满足您的需求吗?关于 Erlang RPC 的详细信息,请访问 http://www.erlang.org/doc/man/rpc.html .在 http://learnyousomeerlang.com/distribunomicon#rpc 中可以找到对 Erlang RPC 的良好处理。 .
关于multithreading - Erlang 节点到节点消息传递吞吐量、超时和保证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13376213/