Erlang 异步消息处理与 gen_server:cast/2
我正在寻找 Erlang 使用 gen_server:cast/2 进行异步消息处理的好例子。
我在 OTP ssh 模块中看到了一个示例,它通过以下方式接收请求 module:handle_cast/2,保存在模块的本地队列中,稍后通过显式向调用者发送消息的方式发回与请求对应的回复消息。当我尝试阅读它时,我几乎无法跟踪代码,也无法理解其思想。
一段伪代码值得赞赏。
I'm looking for good examples of Erlang asynchronous message handling with gen_server:cast/2.
I've seen an example in the OTP ssh module, which receives a request through
Module:handle_cast/2, holding it in a local queue of the module, and sending back a reply message corresponding to the request later, by explicitly sending a message to the caller. When I tried to read it, I could barely keep track of the code, and wasn't able to grasp the idea.
A piece of pseudo code is appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我相信您指的是 ssh_connection_manager 模块。
当您执行
gen_server:cast/2
时,请求将在Module:handle_cast/2
函数中处理。这里需要注意一些事情:handle_cast
参数中,您没有有关发送者的信息,因此您无法 - 除非您在消息本身中发送此信息 - 向其发送回一些结果。gen_server:cast/2
后,不会等待回复。实际上,它甚至不关心消息是否到达(有一些例外)。handle_cast/2
中,您只能返回一个 noreply 或 stop 元组,因此无法在那里返回回复。也就是说,您一直在查看的代码背后的想法应该是(简化事情):
gen_server:call/2
此时,您有两种可能性,具体取决于您是否需要更多信息来计算来自其他客户端 (A) 还是来自同一客户端 (B) 的结果:
gen_server:call/2
询问您最终结果。I believe you're referring to the ssh_connection_manager module.
When you perform a
gen_server:cast/2
, the request is handled in theModule:handle_cast/2
function. A couple of things to notice here:handle_cast
parameters you don't have information about the sender, so you cannot - unless you send this information within the message itself - send back some result to it.gen_server:cast/2
, won't wait for a reply. Actually, it doesn't even care if the message arrived or not (with some exceptions).handle_cast/2
, you can just return a noreply or a stop tuple, so no way to return a reply there.Said that, the idea behind the code you've been looking at should be (simplifying things):
gen_server:call/2
is madeAt this point you have to two possibilities, depending if you need more information to compute your result from other clients (A) or from the same client (B):
gen_server:call/2
.通常,在发送强制转换时您不会期望得到直接回复,否则您将使用 gen_server:call。
一个真实的例子,我有一个 gen_server 来处理一些“通道”,并且有很多用途可以将通道名称附加到错误日志记录中。通道名称存储在 gen_server 的状态中。为了不阻止想要记录错误的进程,我不使用“获取名称”同步调用来获取前置名称,而是使用强制转换发送消息:
强制转换是在一个非常简单的处理程序中处理的,即不返回。
如果您有异步消息要发回,则这完全独立于强制转换的处理。您需要以某种方式知道将这些消息发送到哪里,您必须以某种方式将这些消息存储在 State 中,或者您正在使用固定名称。
通常,您不应该只发送消息,而应该调用接收处理模块的函数(这可能是另一个强制转换或普通消息发送)。
Normally you don't expect a direct reply when sending a cast, otherwise you would use gen_server:call.
A real world example, I have a gen_server that handles some "channels" and there is lots of use to append the channel name to error logging. The channel name is stored in the state of the gen_server. In order not to hold up the process who wants to log an error I don't use a "get name" synchronous call to get the name an prepend but send the messages with casts:
The cast is handled in a quite simple handler, that does not return.
If you have asynchronous messages to send back, this is totally independent of the handling of the cast. You somehow need to know where to send these messages which you have to store in the
State
somehow, or you are using a fixed name.Normally you shouldn't just send a message but rather call a function of the receiving process module (which just might be another cast or plain message sending).