6

我有一个尽可能简单的主管和 GenServer 的混合项目。当我从 iex 打电话时:

EchoCmd.Supervisor.start_link([:Hello])
GenServer.call(:echoserver, :echo)
GenServer.call(:echoserver, :mumble)
GenServer.call(:echoserver, :echo)

:mumble 调用引发异常,然后 GenServer 重新启动,第二个 :echo 调用正常。

如果我以任何其他方式运行代码,Supervisor 将无法重新启动 GenServer。例如,我使用主模块创建项目的 escript,如下所示:

defmodule EchoCmd.Echo do
    def main(args) do
        EchoCmd.Supervisor.start_link([:Hello])
        GenServer.call(:echoserver, :echo)
        GenServer.call(:echoserver, :mumble)
        GenServer.call(:echoserver, :echo)
    end
end

:mumble 调用引发异常,并且 escript 终止,而 Supervisor 没有重新启动 GenServer。

我没有包含 Supervisor 和 Server 模块代码,因为它们在从 iex 调用时工作正常,所以我猜这里不需要它们。

我有概念上的误解吗?这是不可能的,还是我做错了什么?

4

2 回答 2

6

问题不在于您的服务器和主管,而在于您调用它们的方式。如果服务器退出而另一个进程正在等待对 的回复GenServer.call,则调用进程也会退出,因此最后一次调用永远不会发生。GenServer.call这样做的原因是,如果同步调用失败(是同步的,而不是同步的) ,则进程不可能在无效状态下继续GenServer.cast。如果您这样做只是为了测试主管,那么您可以尝试:

defmodule EchoCmd.Echo do
    def main(args) do
        EchoCmd.Supervisor.start_link([:Hello])
        GenServer.cast(:echoserver, :echo)
        GenServer.cast(:echoserver, :mumble)
        GenServer.cast(:echoserver, :echo)
    end
end

它起作用的原因iexiex陷阱出口并允许您输入另一行。

于 2014-11-17T09:00:23.017 回答
4

Escript 行为是正确的。您只是错过了 iex shell 如何“帮助您”。

您在代码中所做的是启动链接进程,而不是使其崩溃。并且由于它是一个链接进程,当它出现故障时,它应该会关闭所有链接进程。可能有一些“例外”,但你的 escript 进程正在发生什么。

shell 和进程主管都可以处理这样的“我死了,你也应该这样”的消息。他们通过改变进程(链接进程,而不是垂死的进程)处理此类消息的方式来做到这一点。它允许他们将它们作为普通消息接收(receive如果您愿意,您可以在子句中接收)而不是特殊的内部消息。为了改变他们使用的这种行为Process.flag( :trap_exit, :true)elixir doc指向eralng 的)。它允许 shell 只打印被杀死进程的死亡,而不是每次你做坏事时死亡。

所以你可以做同样的事情。更改此标志,如果您不想receive对此类消息进行模式匹配。但我认为这不是你要找的。由于您的进程是单例的,并且主管会重新启动,因此您实际上没有任何理由首先链接到它。不需要更新死亡和重启,让主管担心。就像乔·阿姆斯特朗(Joe Armstrong)所说(可能是意译)

您无需知道如何修理自动售货机即可使用它。

所以只是start, 而不是start_link

也就是说,您可能会考虑创建与主管的链接,这也可能在重启过多后死亡(他可能被告知以这种方式行事)。它允许你在你死时带走他(和监督的过程)。或者,他可以与您的主管、申请主管或以其他方式联系起来。这取决于您的域,并且没有错误的决定,您只需要检查什么对您有用。这是设计决策,您必须进行试验或阅读更多相关信息:

http://elixir-lang.org/getting_started/mix_otp/5.html

http://www.erlang.org/doc/design_principles/des_princ.html

http://learnyousomeerlang.com/supervisors

于 2014-11-17T02:20:37.560 回答