作者:mobiledu2502889283 | 来源:互联网 | 2023-05-18 11:45
supervisor监控者supervisor模块提供了一个监控其他进程的进程。通过supervisor能够构建监控树,用于构造容错应用程序。监控者能够启动、关闭及
supervisor监控者
supervisor
模块提供了一个监控其他进程的进程。通过supervisor
能够构建监控树,用于构造容错应用程序。监控者能够启动、关闭及重启它的子进程。
supervisor
进程通过supervisor:start_link(Module, Args)
或supervisor:start_link(SupName, Module, Args)
启动,成功的话返回值为{ok, Pid}
。此时会通过调用回调函数Module:init(Args)
来初始化监supervisor
进程,如果成功,init
将返回{ok, {SupFlags, [ChildSpec]}}
其中,SupFlags
定义了supervisor
进程的重启策略,它是如下的maps:
#{strategy => one_for_one, intensity => 1, period => 5}
或元组{strategy, intensity, period}
strategy
表示子进程的重启策略,主要有以下几种:
one_for_one
:一个子进程挂掉后,只有该子进程会被重启。默认选项;
one_for_all
:一个子进程挂掉后,其他子进程也会被终止,然后重启所有子进程;
rest_for_one
:一个子进程挂掉后,在该子进程后启动的子进程会被终止,然后重启这些子进程;
注意:所有子进程是按照列表顺序去启动的,终止时,按照列表顺序的逆序去终止。
simple_one_for_one
:简单版的one_for_one
,在这种策略下,所有子进程都是动态添加的。此时返回的ChildSpec
只有一个元组。
intensity
和period
共同指定supervisor
的重启限度。默认为1
、5
,表示5
s内最多重启1
次,超过这个限度后,supervisor
进程将会终止所有子进程和它本身。能够有效地防止supervisor
无限重启。
注意,intensity=2
、period=10
与intensity=1
、period=5
是不同的,{1,5}
短时间内不允许重启2次而{2,10}
是允许的。
ChildSpec
定义为以下的maps:
#{id => Id, start => {M,F,A}}, restart => permanet|temporary|transient, shutdown => brutal_kill|TimeOut, type => supervisor|worker, modules => modules()}
或元组{id, start, restart, shutdown, type, modules}
id
为子进程的标识符;
start
是一个{M,F,A}
元组,用于启动子进程,返回{ok,Child}
或{ok,Child,Info}
,Child
为子进程的Pid
;
restart
是指定了子进程终止时的处理策略,permanent
参数表示每次终止都重启,temporary
表示不再重启(即使因为其他进程终止导致本进程终止而后需要重启的情况),transient
表示只有当进程被意外终止才会重启,正常原因包括normal
, shutdown
, or {shutdown,Term}
,默认为permanent
;
shutdown
指定子进程的终止方式,brutal_kill
表示通过调用exit(ChildPid, kill)
终止子进程,TimeOut
表示表示通过调用exit(ChildPid, shutdown)
终止子进程,此时将会等待TimeOut
ms等待子进程返回一个理由为shutdown
的退出信号。当子进程为supervisor
进程时,应该设置成infinity
。默认为50000;
type
指定子进程的类型,默认worker
;
module
指定回调模块,默认为{M,F,A}
中的M
。
注意,在init
返回后,supervisor
会根据子进程列表[ChildSpec]
,启动所有的子进程。supervisor:start_link
是同步调用,在所有子进程启动之前它不会返回。
可以通过supervisor:check_childspecs([ChildSpec])
检查ChildSpec
是否合法。
可以通过supervisor:count_children(SupRef)
获取supervisor
进程的子进程情况。
可以通过supervisor:start_child(SupRef, ChildSpec)
动态启动一个子进程,不过该子进程在supervisor
进程重启后将会丢失。
可以通过supervisor:terminate_child(SupRef, Id)
终止一个子进程,无论该子进程是静态添加抑或是动态添加的。此处的Id
,如果是动态添加的则必须为子进程Pid
。
可以通过supervisor:restart_child(SupRef, Id)
重启一个子进程。此子进程必须在ChildSpecs
中。
可以通过supervisor:delete_child(SupRef, Id)
删除一个子进程,并从ChildSpecs
中删除。
-module(ch_sup).
-behaviour(supervisor).-export([start_link/0]).
-export([init/1]).start_link() ->supervisor:start_link(ch_sup, []).init(_Args) ->SupFlags = #{strategy => one_for_one, intensity => 1, period => 5},ChildSpecs = [#{id => ch3,start => {ch3, start_link, []},restart => permanent,shutdown => brutal_kill,type => worker,modules => [cg3]}],{ok, {SupFlags, ChildSpecs}}.
-module(simple_sup).
-behaviour(supervisor).-export([start_link/0]).
-export([init/1]).start_link() ->supervisor:start_link(simple_sup, []).init(_Args) ->SupFlags = #{strategy => simple_one_for_one,intensity => 0,period => 1},ChildSpecs = [#{id => call,start => {call, start_link, []},shutdown => brutal_kill}],{ok, {SupFlags, ChildSpecs}}.
对于Simplified one_for_one Supervisors
而言,所有的子进程都是通过supervisor:start_child(Sup, [List])
动态添加的,相当于调用apply(call, start_link, []++[List])
即call:start_link([List])
。子进程通过supervisor:terminate_child(SupRef, Pid)
终止。
需要注意的是,Simplified one_for_one Supervisors
子进程的终止是异步的,终止顺序不可预测。