Elixir - 基本主管设置崩溃而不是重新启动子进程
Elixir - Basic supervisor setup crashes instead of restarting the child process
忽略缺少 Mix 配置文件,我编写以下内容:
defmodule Test.Supervisor do
use Supervisor
def start_link do
#"name:" will show up in :observer...
Supervisor.start_link(__MODULE__, [], [name: :"root_supervisor"])
end
def init(args) do
children = [
worker(Test.Method, [], [function: :start, id: "my_root_process"]),
]
supervise(children, [strategy: :one_for_one, name: :root])
end
end
defmodule Test do
def start(_type, _args) do
Test.Supervisor.start_link()
end
end
defmodule Test.Method do
def start do
IO.puts("Expect to see me often... #{self}")
end
end
在第一个 运行(iex -S 混合)后崩溃而没有重新启动应用程序。错误信息是:
=INFO REPORT==== 14-Jan-2016::22:34:04 ===
application: logger
exited: stopped
type: temporary
** (Mix) Could not start application mememe: Test.start(:normal, {}) returned
an error: shutdown: failed to start child: "my_root_process"
** (EXIT) :ok
但是,如果我将 Test.start()
更改为直接调用 Test.Method.start()
,如下所示:
defmodule Test do
def start(_type, _args) do
Test.Method.start()
end
end
然后 运行 没问题,但是代码不会被监督。
我很确定我在实施或理解方面犯了一个基本错误,但那个错误到底是什么?
我会尝试将 Test.Method.start
函数更改为 Test.Method.start_link
函数,并在您选择 worker 函数时停止使用 function: :start
。默认情况下,监管者调用 start_link
并且没有理由破坏这些语义,因为监管者将始终 link 到被监管的进程。如果这不起作用,那么至少我们已经排除了这方面的问题。
您的代码有几个问题。首先,你需要一个 long 运行 函数来监督。类似于:
def loop do
receive do
_anything -> IO.puts "Expect to see me often"
end
loop
end
然后在Test.Method
模块中,你必须生成它。
def start do
IO.puts("Starting...")
pid = spawn_link(&loop/0)
{:ok, pid}
end
启动函数 return 的元组 {:ok, pid_to_supervise}
很重要。它使您的应用程序崩溃,因为主管希望有一个进程进行监视,但只得到 :ok
return 由 IO.puts
编辑的原子。工人规范 不会产生 新进程。它需要一个函数,它将 return 派生进程的 pid。
你还应该 link 监督进程的主管,所以最后将函数重命名为 start_link
可能是个好主意,而不是像 @Jason Harrelson 那样 start
建议。
这应该足以正确启动您的项目。请注意,您不会在观察者 Applications
部分看到您的流程。您没有使用 Application
行为,因此您的 root_supervisor
将漂浮在某处。您可以在 Processes
选项卡中找到它。 my_root_process
是与 supervisor 一起使用的 id,因此即使在 Processes
选项卡中也不可见。
这种方式的生成过程很容易用于教育目的,但在现实世界的系统中,您希望您的过程遵循 OTP 设计原则。意思是reacting to system messages, better logging, tracing and debugging。制作满足所有要求的过程非常困难,但您不必手动完成。所有的行为都为你贯彻了这些原则。
因此,不要使用循环生成进程,而是尝试使用 GenServer
。
忽略缺少 Mix 配置文件,我编写以下内容:
defmodule Test.Supervisor do
use Supervisor
def start_link do
#"name:" will show up in :observer...
Supervisor.start_link(__MODULE__, [], [name: :"root_supervisor"])
end
def init(args) do
children = [
worker(Test.Method, [], [function: :start, id: "my_root_process"]),
]
supervise(children, [strategy: :one_for_one, name: :root])
end
end
defmodule Test do
def start(_type, _args) do
Test.Supervisor.start_link()
end
end
defmodule Test.Method do
def start do
IO.puts("Expect to see me often... #{self}")
end
end
在第一个 运行(iex -S 混合)后崩溃而没有重新启动应用程序。错误信息是:
=INFO REPORT==== 14-Jan-2016::22:34:04 ===
application: logger
exited: stopped
type: temporary
** (Mix) Could not start application mememe: Test.start(:normal, {}) returned
an error: shutdown: failed to start child: "my_root_process"
** (EXIT) :ok
但是,如果我将 Test.start()
更改为直接调用 Test.Method.start()
,如下所示:
defmodule Test do
def start(_type, _args) do
Test.Method.start()
end
end
然后 运行 没问题,但是代码不会被监督。 我很确定我在实施或理解方面犯了一个基本错误,但那个错误到底是什么?
我会尝试将 Test.Method.start
函数更改为 Test.Method.start_link
函数,并在您选择 worker 函数时停止使用 function: :start
。默认情况下,监管者调用 start_link
并且没有理由破坏这些语义,因为监管者将始终 link 到被监管的进程。如果这不起作用,那么至少我们已经排除了这方面的问题。
您的代码有几个问题。首先,你需要一个 long 运行 函数来监督。类似于:
def loop do
receive do
_anything -> IO.puts "Expect to see me often"
end
loop
end
然后在Test.Method
模块中,你必须生成它。
def start do
IO.puts("Starting...")
pid = spawn_link(&loop/0)
{:ok, pid}
end
启动函数 return 的元组 {:ok, pid_to_supervise}
很重要。它使您的应用程序崩溃,因为主管希望有一个进程进行监视,但只得到 :ok
return 由 IO.puts
编辑的原子。工人规范 不会产生 新进程。它需要一个函数,它将 return 派生进程的 pid。
你还应该 link 监督进程的主管,所以最后将函数重命名为 start_link
可能是个好主意,而不是像 @Jason Harrelson 那样 start
建议。
这应该足以正确启动您的项目。请注意,您不会在观察者 Applications
部分看到您的流程。您没有使用 Application
行为,因此您的 root_supervisor
将漂浮在某处。您可以在 Processes
选项卡中找到它。 my_root_process
是与 supervisor 一起使用的 id,因此即使在 Processes
选项卡中也不可见。
这种方式的生成过程很容易用于教育目的,但在现实世界的系统中,您希望您的过程遵循 OTP 设计原则。意思是reacting to system messages, better logging, tracing and debugging。制作满足所有要求的过程非常困难,但您不必手动完成。所有的行为都为你贯彻了这些原则。
因此,不要使用循环生成进程,而是尝试使用 GenServer
。