如何解决使用gen_server:cast / 2进行Erlang异步消息处理
|| 我正在寻找使用gen_server:cast / 2处理Erlang异步消息的良好示例。 我已经在OTP ssh模块中看到了一个示例,该模块通过接收请求 Module:handle_cast / 2,将其保存在模块的本地队列中,然后通过显式发送消息给调用方,稍后发送回对应于该请求的答复消息。当我尝试阅读它时,我几乎无法跟踪代码,也无法理解这个想法。 一段伪代码是值得赞赏的。解决方法
我相信您指的是ssh_connection_manager模块。
当执行
gen_server:cast/2
时,将在Module:handle_cast/2
函数中处理请求。这里有几件事要注意:
在“ 2”参数中,您没有有关发件人的信息,因此,除非您在消息本身内发送此信息,否则您将无法发送回一些结果。
客户端发出“ 0”后,将不等待答复。实际上,它甚至不关心消息是否到达(有一些例外)。
在handle_cast/2
中,您只能返回noreply或stop tuple,因此无法在此处返回答复。
话虽如此,您一直在看的代码背后的想法应该是(简化事情):
进行初始同步“ 5”
客户端的“发件人”传递到服务器并保存到其状态(实际上,似乎使用该参数创建了一个额外的过程)。当您无法在handle_call时计算返回值时,此技巧很有用。
此时,您有两种可能性,取决于您是否需要更多信息来计算来自其他客户端(A)或同一客户端(B)的结果:
A.在handle_call中返回类似{noreply NewState}的内容。这将使您有可能在客户端仍处于等待状态时处理其他请求。准备好结果后,您可以使用gen_server:reply()将其发送回客户端。
B.将{reply,ok,State}返回给客户。客户端将继续执行,也许执行一系列的cast / 2。然后,客户会以新的gen_server:call/2
询问您最终的结果。
, 通常,在发送演员表时,您不会期望直接答复,否则您将使用gen_server:call。
一个真实的例子,我有一个处理某些\“ channels \”的gen_server,在将通道名附加到错误日志中有很多用途。通道名称存储在gen_server的状态中。为了不拖延谁想要记录错误的过程,我不使用\“ get name \”同步调用来获取名称的前缀,而是使用强制类型转换发送消息:
error(Pid,Tags) ->
gen_server:cast(Pid,{log,error_report,Tags}).
warning(Pid,warning_report,Tags}).
info(Pid,info_report,Tags}).
强制转换是在非常简单的处理程序中处理的,该处理程序不会返回。
handle_cast({log,Report,Tags},#state{name=Name}=State) ->
error_logger:Report([{chan,Name} | Tags]),{noreply,State};
如果您有异步消息要发回,则这完全独立于演员表的处理。您以某种方式需要知道将这些消息发送到哪里,您必须以某种方式将它们存储在“ 9”中,或者您使用的是固定名称。
通常,您不仅应该发送一条消息,还应该调用接收处理模块的功能(可能只是另一种强制发送或普通消息发送)。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。