1.概念:
supervisor是OTP框架四大行为之一,它用于监视别的进程,当一个进程崩溃是,它能够快速重启该进程,并根据不同的策略做出不同的行为。
2.常用函数:
1.start_link({local/global,NAME}, MODULE, Args).
创建一个supervisor的进程服务器,local为本地进程,global为全局进程,NAME为该进程名,MODULE为回调模块,调用该MODULE的init([])函数,Args为init的参数列表。
2.init([]) -> Result.
1. Result格式为:{ok,{SupFlags,[ChildSpec]}} | ignore,SupFlags通常为形式为{How, Max, Within}:在多长时间内(Within)重启了几次(Max),如何重启(HOW 重启策略);设计最大重启频率是为了避免反复重启进入死循环,一旦超出了此阈值,supervisor进程会结束掉自己以及它所有的子进程,并通过进程树传递退出消息,更上层的supervisor就会采取适当的措施,要么重启终止的supervisor要么自己也终止掉.
2. How通常有以下几种格式:
one_for_one : 若一个子进程崩溃,马上把他重启。
one_for_all : 如果子进程终止,所有其它子进程也都会被终止,然后所有进程都会被重启.
rest_for_one:如果一个子进程终止,在这个进程启动之后启动的进程都会被终止掉.然后终止掉的进程和连带关闭的进程都会被重启.
3.ChildSpec为添加的子进程列表,格式会在start_child说明。
3.start_child(SupRef, ChildSpec) -> startchild_ret()
1.SupRef为supervisor的进程名,ChildSpec为要添加并开启的子服务器。
2.ChildSpec格式如下:
1.Tag
这是一个原子类型的标签,将来可以用它指代工作进程(如果有必要的话)。
2.{Mod, Func, ArgList}
它定义了监控器用于启动工作器的函数,将被用作 apply(Mod, Fun, ArgList) 的参数。
3.Restart = permanent | transient | temporary
permanent (永久)进程总是会被重启。 transient (过渡)进程只有在以非正常退出值
终止时才会被重启。 temporary (临时)进程不会被重启。
4.Shutdown
这是关闭时间,也就是工作器终止过程允许耗费的最长时间。如果超过这个时间,工作
进程就会被杀掉。(还有其他值可用,参见 supervisor 的手册页。)
5.Type = worker | supervisor
这是被监控进程的类型。可以用监控进程代替工作进程来构建一个由监控器组成的树。
6.[Mod1]
如果子进程是监控器或者 gen_server 行为的回调模块,就在这里指定回调模块名。
4.restart_child(SupRef, Id) -> Result
重启名为SupRef服务器中Pid为Id的子进程。
5.delete_child(SupRef, Id) -> Result
删除该子进程,但前提必须得停止该进程。
6.terminate_child(SupRef, Id) -> Result
停止该子进程
常用就着几个。
3.小例子
mysupervisor.erl
-module(mysupervisor).
-compile(export_all).
-behavior(supervisor).
init([]) ->
{ok, {{one_for_all, 10, 10}, []}}.
myserver.erl
-module(myserver).
-behavior(gen_server).
-compile(export_all).
start_link() ->
gen_server:start_link({local, ?MODULE},?MODULE,[],[]).
init([]) ->
ID = ets:new(pp,[set]),
{ok,ID}.
add_man(Key,Value) ->
gen_server:call(?MODULE,{add, Key, Value}).
delete_man(Key) ->
gen_server:call(?MODULE,{del,Key}).
query_man(Key) ->
gen_server:call(?MODULE,{qu,Key}).
handle_call({add, Key, Value}, _From, State) ->
ets:insert(State,{Key, Value}),
{reply,{ok,successs},State};
handle_call({del,Key}, _From, State) ->
Reply = case ets:lookup(State,Key) of
[] -> {no_the_man};
_ -> {del_the_man}
end,
{reply, Reply, State};
handle_call({qu,Key}, _From, State) ->
Reply = case ets:lookup(State, Key) of
[] -> {no_the_man};
Value -> {Key, Value}
end,
{reply, Reply, State}.