基本的Elixir OTP服务器表现奇怪

时间:2016-09-18 19:39:10

标签: elixir otp supervisor

我有这个代码,它是一个基本的OTP服务器:

defmodule Clients do
use Application  
require Logger


def stuff do
    Logger.debug "Clients.start/0"
   # {:ok, pid} = Task.Supervisor.start_child(Clients.TaskSupervisor, fn -> doclient end)
end

def doclient(port) do
    Logger.debug "Clients.doclient/0"

    {:ok, socket} = :gen_tcp.listen(port,[:binary, packet: :line, active: false, reuseaddr: true])

#if this is under 2000ms there the process exits with a shutdown error 
    :timer.sleep(1500)

end

def start(_type, _args) do
    import Supervisor.Spec
    Logger.debug "Clients.init/1"

    children = [
        supervisor(Task.Supervisor, [[name: Clients.TaskSupervisor]]),
        worker(Task, [Clients, :doclient, [4040]])
    ]
    opts = [strategy: :one_for_one, name: Clients.Supervisor]
    Supervisor.start_link(children, opts)
end

end

iex的输出是:

iex(1)> Clients.start(1,2)

20:07:19.879 [debug] Clients.init/1

20:07:19.889 [debug] Clients.doclient/0
{:ok, #PID<0.141.0>}
iex(2)> 
20:07:21.402 [debug] Clients.doclient/0

20:07:22.909 [debug] Clients.doclient/0

20:07:24.413 [debug] Clients.doclient/0
** (EXIT from #PID<0.139.0>) shutdown

如果doclient / 1定时器调用时间小于2秒,则会发生上述关闭,但是否则它会愉快地消失。我不知道为什么?如果我想让doclient / 1执行一些占用时间不到2秒的任意代码(不管怎么说这不是一个可靠的时期),这个调用总是会爆炸。

1 个答案:

答案 0 :(得分:1)

您正在使用Task作为您的工作人员。所以会发生的事情是,一旦Task从睡眠中醒来,它就会完成它的工作并且这个过程就会消失。在您的主管规范中,您要求:

children = [
  supervisor(Task.Supervisor, [[name: Clients.TaskSupervisor]]),
  worker(Task, [Clients, :doclient, [4040]])
]
opts = [strategy: :one_for_one, name: Clients.Supervisor]
Supervisor.start_link(children, opts)

告诉OTP如果它以任何方式完成或消失,就重新启动你的工作人员。因此,在1.5秒(您的睡眠时间)之后,主管开始另一项任务。它在5秒的时间内完成3次。

Supervisor.start_link具有指定重启强度的默认选项。你可以在这里找到文档:

http://elixir-lang.org/docs/stable/elixir/Supervisor.Spec.html#supervise/2

默认值是5秒内最多3次重启。这就是为什么你的主管以1.5秒的睡眠时间关闭,并且以2秒的间隔快乐地继续前进。

总而言之,我认为你需要重新考虑在这个监督树中使用任务。由于你没有提到它是什么,所以不可能猜出什么最适合你的用例。

HTH