【问题标题】:Erlang asynchronous message handling with gen_server:cast/2Erlang 异步消息处理与 gen_server:cast/2
【发布时间】:2011-09-14 10:59:24
【问题描述】:

我正在寻找使用 gen_server:cast/2 处理 Erlang 异步消息的好例子。

我在 OTP ssh 模块中看到了一个例子,它通过 模块:handle_cast/2,将其保存在模块的本地队列中,稍后通过显式向调用者发送消息,回送与请求对应的回复消息。当我试图阅读它时,我几乎无法跟踪代码,也无法掌握这个想法。

感谢一段伪代码。

【问题讨论】:

标签: erlang gen-server


【解决方案1】:

我相信您指的是 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被制作
  • 客户端的From 被传递到服务器并保存到它的状态(实际上,似乎使用该参数创建了一个额外的进程)。当您无法在 handle_call 时计算返回值时,此技巧很有用。
  • 此时您有两种可能性,具体取决于您是需要更多信息来计算来自其他客户端 (A) 还是来自同一客户端 (B) 的结果:

    • A.在 handle_call 中返回类似 {noreply NewState} 的内容。这将使您能够在客户端仍然持有时处理其他请求。当结果准备好后,您可以使用 gen_server:reply() 将其发送回客户端。
    • 乙。将 {reply, ok, State} 返回给客户端。客户端将继续执行,可能会执行一系列 cast/2。然后,客户会用新的gen_server:call/2 询问您的最终结果。

【讨论】:

  • 感谢您的澄清。现在我记得代码的流程。我应该写 ssh 本身就是一种行为。
  • 当你的意思是客户端还在持有,你的意思是客户端被阻塞了,不能继续执行?有没有办法让它不阻塞?可以得到延迟答复吗?还是最好像 jj1bdx 所说的那样创建自定义行为?
  • 我认为这可能会有所帮助trapexit.org/Building_Non_Blocking_Erlang_apps
【解决方案2】:

通常您在发送演员表时不会期望直接回复,否则您会使用 gen_server:call。

一个真实的例子,我有一个处理一些“通道”的 gen_server,并且有很多用处将通道名称附加到错误日志中。通道名称存储在 gen_server 的状态中。为了不阻止想要记录错误的进程,我不使用“获取名称”同步调用来获取名称,而是使用强制类型转换发送消息:

error(Pid, Tags) ->
    gen_server:cast(Pid, {log, error_report, Tags}).

warning(Pid, Tags) ->
    gen_server:cast(Pid, {log, warning_report, Tags}).

info(Pid, Tags) ->
    gen_server:cast(Pid, {log, info_report, Tags}).

转换在一个非常简单的处理程序中处理,不会返回。

handle_cast({log, Report, Tags}, #state{name=Name}=State) ->
    error_logger:Report([{chan, Name} | Tags]),
    {noreply, State};

如果您有异步消息要发回,这完全独立于演员表的处理。您不知何故需要知道将这些消息发送到哪里,您必须以某种方式将这些消息存储在 State 中,或者您使用的是固定名称。

通常您不应该只发送消息,而是调用接收进程模块的函数(可能是另一个强制转换或普通消息发送)。

【讨论】:

    猜你喜欢
    • 2011-08-27
    • 2014-05-23
    • 1970-01-01
    • 2017-02-12
    • 1970-01-01
    • 1970-01-01
    • 2016-08-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多