Erlang Node to Node Messaging吞吐量,超时和保证

时间:2012-11-14 09:36:09

标签: multithreading erlang

现在,假设我们正在设计一个应用程序,由2个Erlang节点组成。在节点A上,将有很多进程,数千个订单。这些进程通过向节点B上的已注册进程发送消息来访问节点B上的资源。
在节点B,假设您通过执行以下函数启动了进程:

{{ 2}} 在节点A上,任何想要在节点B上的给定模块中执行任何功能的进程都使用以下代码:
start_server()->
    register(zeemq_server,spawn(?MODULE,server,[])),ok.
server()-> receive {{CallerPid, Ref}, {Module, Func, Args}} -> Result = (catch erlang:apply(Module, Func, Args)), CallerPid ! {Ref, Result}, server(); _ -> server() end.
因此,假设节点B上的进程zeemq_server永远不会关闭,并且节点A和B之间的网络连接始终处于启动状态,请回答以下问题:

Qn 1 :由于节点B上只有一个接收进程,因此其邮箱最有可能一直是满的。这是因为,节点A上的进程很多,并且在给定的时间间隔(例如2秒),每个进程至少,对Node B服务器进行一次调用。在哪种方式,接收可以在Node B上冗余? ,例如进程组e.t.c.并解释(概念)这将如何取代上面的服务器端代码。显示客户端会发生什么变化。

Qn 2 :在节点B上只有一个接收器的情况下,进程邮箱中是否允许有最大数量的消息?如果一个进程的邮件被充斥着过多的邮件,那么erlang会如何回应呢?

Qn 3 :在哪些方面,使用上面显示的概念,我可以保证每个发送请求的进程在超时发生之前尽快回复答案吗?可以将Node 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.
上面显示的方法可能会增加节点B上运行的进程的瞬时数量,这可能会因内存而极大地影响服务。但是,它看起来很好,并使server()循环立即返回以处理下一个请求。你对这个修改有什么看法?

最后:说明如何在节点B上实现Pool of receiver Threads,但在节点A方面似乎只有一个Name。这样,传入的消息在接收者之间被多路复用线程和这组进程中共享的负载。保持问题的含义相同。

谢谢Erlangers

2 个答案:

答案 0 :(得分:2)

除了内存量之外,进程邮箱中的最大邮件数是无限制的。

此外,如果您需要检查邮箱大小,请使用

erlang:process_info(self(),[message_queue_len,messages]).

这将返回如下内容:

[{message_queue_len,0},{messages,[]}]

我建议您先将服务器转换为gen_server。这是你的工人。

接下来,我建议使用poolboy(https://github.com/devinus/poolboy)来创建服务器实例池作为poolboy worker(在他们的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的良好处理。

答案 1 :(得分:0)

IMO产生一个处理每个请求的新流程可能过度,但很难说不知道每个请求需要做什么。

您可以拥有一个进程池来处理每个消息,使用循环方法分发请求或根据请求类型处理它,将其发送到子进程或生成进程。您还可以通过查看其msg队列并在重载时启动新子项来监视池化进程的负载。使用主管..只需在init中使用send_after每隔几秒钟监控负载并采取相应措施。如果可以的话,使用OTP,有开销,但值得。

我不会将http用于专线通信,我相信它的开销太大了。您可以使用一组进程来控制负载来处理它。