elang的supervisor
init返回
{ok, sup_flags(), child_spec()}
sup_flags()是针对这个supervisor的属性,child_spec()是子进程规范列表。
监督者标识
sup_flags() = #{strategy => strategy(), % optional intensity => non_neg_integer(), % optional period => pos_integer()} % optional
四种重启策略strategy
- one_for_one(default) 这类子进程其中一个挂了,只有这个进程会被重启,其他不受影响。
- one_for_all 这类子进程任何一个挂了,所有进程全部重启。
- rest_for_one 这类进程某个子进程挂了,那么在这个挂了的子进程后面启动的所有子进程都会按顺序重启。
- simple_one_for_one 这是one_for_one的简化版,但是所有子进程都是基于相同的spec动态启动,这些子进程都是同一spec的实例。
重启密度
重启密度设置是为了避免无休止的进程重启。重启密度由 intensity(次数) 和 period(s) 确定,超过这个重启密度,supervisor就会终止所有的 子进程,然后终止自己。
子进程规范
child_spec() = #{id => child_id(), % mandatory start => mfargs(), % mandatory restart => restart(), % optional shutdown => shutdown(), % optional type => worker(), % optional modules => modules()} % optional
子进程启动方式start()
{Module, Function, Args},子进程通过这个函数启动。simple_one_for_one 的时候,Args还要加上 start_child/2 中的参数。
restart()
定义被终止的进程什么时候会被重启。
- permanent 永久的 这种类型的子进程只要终止都会被重启。
- temporary 临时的 这种类型的子进程无论如何都不会被重启,就算strategy是one_for_one,rest_for_one.
- transient 瞬时的 这种类型的子进程只有在非正常终止之后才会被重启。即不是normal, shutdown, or {shutdown,Term}这类终止原因。
shutdown()
定义进程应该被怎么杀死。
- brutal_kill 无条件使用exit(Child,kill)粗暴地杀死。
- 整数(ms) 如果是整数,就是超过这个时间就使用exit(Child,shutdown)杀死。
- infinity 一直等待,当子进程时supervisor的时候,要等待子进程的子进程终止之后才终止supervisor。当然子进程是worker的时候也可以使用这种方式。
type()
指明这个子进程是worker还是supervisor。
module()
指出进程使用那个模块。
关于 start_child/2
- supervisor 的 init 指定的方式如果是 one_for_one 的时候,在启动了supervisor后会自动将制定了spec的worker或sub-supervisor启动起来。
- 有时候需要手动调用start_child来在该sup下面启动worker,这时候如果不适用init的spec,那就是用start_child(Sup, NewSpec)。NewSpec就是 该worker的spec。如果init中制定simple_one_for_one的方式,需要临时增加worker,这时候可以使用start_child(Sup, OptsList),OptList是参数, 这个参数会append在spec中的MFA指定的A后面,即真正执行的时候时MF(A+OptsList)。