且听疯吟如此生活三十年
Erlang/OTP Supervisor : one-for-one and simple-one-for-one

Supervisor 的四个 Restart Strategy 中,关于 one for one 和 simple one for one , 虽然很多地方都说 simple one for one 是 one for one 的简化版,但两者之间还是有一些不同。

1. 先来看一个简单的 one for one 和 simple one for one 的例子

  • one for one

    1
    2
    3
    4
    init(_Args) ->
    {ok, {{one_for_one, 1, 60},
    [{call, {call, start_link, []},
    permanent, brutal_kill, worker, [call]}]}}.
    • simple one for one
    1
    2
    3
    4
    init(_Args) ->
    {ok, {{simple_one_for_one, 0, 1},
    [{call, {call, start_link, []},
    permanent, brutal_kill, worker, [call]}]}}.

    初始化方法非常相似

2. 启动 Supervisor

  • one for one
    启动时,会同时启动一个子进程
  • simple one for one
    启动时,supervisor 并不会启动任何子进程,所有的子进程都是通过 supervisor:start_child(Sup, List) 来动态添加的

3. 允许的 Child Type

  • one for one
    允许不同的 child type,所以每次添加子进程都需要传递完整的 child spec
  • simple one for one
    只能有一个 child type,不同的 child instance 可以共享同一个 child spec

4. 添加子进程

  • one for one
    添加子进程的时候传递的是子进程规格

    1
    supervisor:start_child(Sup, ChildSpec)
  • simple one for one
    添加子进程的时候传递的是任意的值列表,它将会被添加到子进程规格中的参数列表中,即实际上是通过 apply(call, start_link, [] ++ List) 来启动的

    1
    supervisor:start_child(Sup, List)

相同的是,如果 supervisor 挂了,并且被 restart,之前动态添加的子进程将会全部丢失

5. Supervisor 停止

  • one for one
    按照启动 Spec 相反的顺序停止所有子进程,然后停止自身
  • simple one for one
    由于 supervisor 启动的是同一子进程的多个 instance,因此在停止的时候不存在顺序,
    在定义 Shutdown Strategy 的时候应该注意其 terminate 表现的区别。