Erlang -- 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, % optional
  intensity => 1,          % optional
  period => 5}             % optional

或元组{strategy, intensity, period}

strategy表示子进程的重启策略,主要有以下几种:
one_for_one:一个子进程挂掉后,只有该子进程会被重启。默认选项;
one_for_all:一个子进程挂掉后,其他子进程也会被终止,然后重启所有子进程;
rest_for_one:一个子进程挂掉后,在该子进程后启动的子进程会被终止,然后重启这些子进程;
注意:所有子进程是按照列表顺序去启动的,终止时,按照列表顺序的逆序去终止。
simple_one_for_one:简单版的one_for_one,在这种策略下,所有子进程都是动态添加的。此时返回的ChildSpec只有一个元组。

intensityperiod共同指定supervisor的重启限度。默认为15,表示5s内最多重启1次,超过这个限度后,supervisor进程将会终止所有子进程和它本身。能够有效地防止supervisor无限重启。
注意,intensity=2period=10intensity=1period=5是不同的,{1,5}短时间内不允许重启2次而{2,10}是允许的。

ChildSpec定义为以下的maps:

#{id => Id,       		  % mandatory
  start => {M,F,A}},      % mandatory
  restart => permanet|temporary|transient, % optional
  shutdown => brutal_kill|TimeOut, % optional
  type => supervisor|worker,       % optional
  modules => modules()}   % optional

或元组{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中删除。

两个例子
%% one_for_one Supervisors
-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}}.
%% Simplified one_for_one Supervisors
-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子进程的终止是异步的,终止顺序不可预测。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值