erlang supervisor simple_one_for_one實例


simple_one_for_one vs one_for_one:

相同點:

這種Restart Strategy和one_for_one基本相同(即當一個child process掛掉后,僅僅重啟該child process 而不影響其他child process)。

異同點:

1, simple_one_for_one supvisor啟動時不會啟動任何子進程,所有子進程都只能通過調用 supervisor:start_child(Sup, Args) 來動態啟動。

2, simple_one_for_one supvisor持有child process的定義,並有一個dict存放數據, 其實就是如干個child process,共享一份數據。

3, 一個simple_one_for_one supervisor只有一個(single)simple_one_for_one的定義, 也就是說它只能生產出一種類型worker process。

 

supervisor:start_child(Sup, Args) :

    Sup:  Supervisor的Pid或者registered Name.

    Args: 當supervisor的類型是simple_one_for_one時,Args會追加到spec的參數中。

例如:

-module(simple_sup).
-behaviour(supervisor).

-export([start_link/0]).
-export([init/1]).

start_link() ->
    supervisor:start_link({local,?MODULE}, ?MODULE, []).

init(_Args) ->
  {M, F, A} = _Args,
    {ok, {{simple_one_for_one, 0, 1},
          [{M, {M, F, A},
            temporary, brutal_kill, worker, [M]}]}}.

調用supervisor:start_child(simple_sup, Args)后,最終啟動子進程的代碼會是:apply(M, F, A++Args).

調用supervisor:start_child(Sup, Args)可能會遇到的錯誤:

1, noproc: 可能的原因是在調用supervisor:start_link時沒寫參數{local, ?MODULE},即上面代碼紅色部分,此時進程Sup並不存在,所以會產生

                 noproc錯誤。

2,undef: 可能的原因是A++Args后,與child process的start_link函數參數不一致。

 

實例代碼:

     實例包含兩部分,一是監控普通進程(normal_process.erl),二是監控gen_server進程(gen_server_process.erl)。

common.hrl

%%-define(CALL, normal_process).
-define(CALL, gen_server_process).

simple_sup.erl

-module(simple_sup).
-behaviour(supervisor).

-export([start_link/0]).
-export([init/1]).

-include("common.hrl").

start_link() ->
    supervisor:start_link({local, ?MODULE}, simple_sup, []).

init(_Args) ->
    {ok, {{simple_one_for_one, 0, 1}, 
          [{?CALL, {?CALL, start_link, []},
          temporary, brutal_kill, worker, [?CALL]}]}}.

normal_process.erl

-module(normal_process).

-export([start_link/0, start_loop/1]).

start_link() ->
    proc_lib:start_link(?MODULE, start_loop, [self()]).

start_loop(Parent) ->
    proc_lib:init_ack(Parent, {ok, self()}),
    loop().

loop() ->
    receive
        Args ->
            io:format("~p~n", [Args])
    end.

gen_server_process.erl

-module(gen_server_process).
-behaviour(gen_server).
-export([start_link/0]).

%% gen_server callbacks
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
         terminate/2, code_change/3]).

%% interface
-export([start/0, stop/0, echo/1]).

%% interface implement
start()      -> start_link().
stop()       -> gen_server:call(?MODULE, stop).
echo(String) -> gen_server:call(?MODULE, {echo, String}).

%% gen_server callbacks implement
start_link() -> gen_server:start_link({local,?MODULE}, ?MODULE, [], []).

init([]) ->
    {ok, 0}. 

handle_call({echo, String}, _From, Tab) ->  
    Reply = String,
    {reply, Reply, Tab};

handle_call(stop, _From, Tab) ->
    {stop, normal, stopped, Tab}.

handle_cast(_Msg, State) -> {noreply, State}.
handle_info(_Info, State) -> {noreply, State}.
terminate(_Reason, _State) -> ok. 
code_change(_OldVsn, State, _Extra) -> {ok, State}.

編譯命令

c(simple_sup).
c(normal_process).
c(gen_server_process).

測試命令:

simple_sup:start_link().
supervisor:start_child(simple_sup, []).

測試通過start_child啟動普通進程:

修改common.hrl:-define(CALL, normal_process). 執行編譯命令 + 測試命令

測試通過start_child啟動gen_server進程:

修改common.hrl:-define(CALL, gen_server_process). 執行編譯命令 + 測試命令

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM