Erlang入門:構建application練習5(監督樹)

來源:互聯網
上載者:User

標籤:erlang   入門教程   執行個體   application   監督樹   

1、前言在《Erlang入門:構建application練習4(進程link的作用)》一文中,
提到了一個問題:
如果系統進程內部發生了錯誤而異常退出,將會出現什麼情況?
在application中,像bank_center這樣的系統進程,如果終止了,整個系統就無法正常運行,為了讓bank_center意外終止時能自動重啟,這裡就要請Erlang的監督樹出來幫忙了。
示範項目bank3目錄結構:



2、編寫監督樹回調模組bank_sup.erl監督樹的回調模組只有一個函數init/1
%% @author Rolong<[email protected]>-module(bank_sup).-behaviour(supervisor).-export([start_link/0]).-export([init/1]).%% 定義一個啟動本監督樹的APIstart_link() ->    supervisor:start_link({local, ?MODULE}, ?MODULE, []).init([]) ->    %% 啟動2個子進程    BankCenterSpec = {      center %% 指定本進程(在子進程中唯一)的名稱      ,{bank_center, start_link, []} %% 進程啟動函數:{M,F,A}      ,transient %% 重啟策略:permanent | transient | temporary      ,5000 %% 關閉方式:brutal_kill | int()>0 | infinity      ,worker %% 進程類型:worker 或 supervisor      ,[bank_center] %% 回調模組名稱:[Module] | dynamic     },    BankCenterSpec2 = {      center2      ,{bank_center2, start_link, []}      ,transient      ,5000      ,worker      ,[bank_center2]     },    %% {ok, {{RestartStrategy, MaxR, MaxT}, [ChildSpec]}}    {ok, {{one_for_one, 5, 30}, [BankCenterSpec, BankCenterSpec2]}}.

重啟策略:
(1)、permanent:終止後總是會被重啟
(2)、transient:意外終止後會被重啟
什麼事意外?
就是進程退出的Reason不是以下3種之一:
normal | shutdown | {shutdown, Term}
(3)、temporary:終止後不會被重啟

關閉方式:
(1)、brutal_kill:野蠻方式,直接exit(Pid,kill)
(2)、大於0的整數:先exit(Child,shutdown),如果超過了指定的毫秒數還沒有收到退出訊號{‘EXIT‘, PiD, Reason},再exit(Pid,kill)
(3)、infinity:exit(Child,shutdown),然後一直等到退出訊號{‘EXIT‘, PiD, Reason}為止

問題:如果某個子進程的重啟策略為permanent,當這個子進程發生異常,啟動後就立馬結束,然後又立馬被監督樹重啟,如此下去,如何是好?

init/1的返回值{ok, {{RestartStrategy, MaxR, MaxT}, [ChildSpec]}}中的MaxR, MaxT就是為解決這個問題而生的。
樣本中MaxR=5, MaxT=30,表示30秒內,允許總重啟次數為5,
如果總重啟次數超過5次,整個監督樹下的進程都會被終止,最後監督樹自身也會終止,整個application也就此停止運行了。

init/1的返回值{ok, {{RestartStrategy, MaxR, MaxT}, [ChildSpec]}}中的RestartStrategy是監督樹的重啟策略,共有如下4種:
(1)、one_for_one:這是最常用的一直策略。當某個子進程終止時,只重啟這個子進程
(2)、simple_one_for_one:和one_for_one一樣,只是子進程是監督樹啟動後再動態增加的。如遊戲中,假設一個玩家就一個進程,每建立一個玩家進程之後,把這個進程添加到監督樹中,這就是simple_one_for_one
(3)、one_for_all:不常用,需瞭解請見文檔
(4)、rest_for_one:不常用,需瞭解請見文檔

3、監督樹實驗bank_center/bank_center2中增加以下訊息處理:
handle_info(error, Money) ->%% Error Return ...{ok, Money};handle_info(force_stop, Money) ->{stop, "Force STOP", Money};handle_info(normal_stop, Money) ->{stop, normal, Money};handle_info(shutdown, Money) ->{stop, shutdown, Money};handle_info({shutdown,Term}, Money) ->{stop, {shutdown,Term}, Money};

3.1、測試{RestartStrategy, MaxR, MaxT}={one_for_one, 5, 30}
Eshell V5.10.4 (abort with ^G)1> appmon:start().{ok,<0.40.0>}2> bank_center ! normal_stop.##[<0.38.0>bank_center:59] terminate: normalnormal_stop##[<0.51.0>bank_center:23] Start bank_center ...3> bank_center ! normal_stop.##[<0.51.0>bank_center:59] terminate: normalnormal_stop##[<0.53.0>bank_center:23] Start bank_center ...4> bank_center ! normal_stop.##[<0.53.0>bank_center:59] terminate: normalnormal_stop##[<0.55.0>bank_center:23] Start bank_center ...5> bank_center2 ! normal_stop.##[<0.39.0>bank_center2:59] terminate: normalnormal_stop##[<0.57.0>bank_center2:23] Start bank_center2 ...6> bank_center2 ! normal_stop.##[<0.57.0>bank_center2:59] terminate: normalnormal_stop##[<0.59.0>bank_center2:23] Start bank_center2 ...7> bank_center2 ! normal_stop.##[<0.59.0>bank_center2:59] terminate: normal##[<0.55.0>bank_center:59] terminate: shutdownnormal_stop8> ##[<0.34.0>bank_app:16] Stop bank_app!=INFO REPORT==== 17-Jan-2015::16:19:15 ===application: bankexited: shutdowntype: temporary


從上面可以看出,當一個被監督的進程終止後,立即被重啟了,其他進程不受影響,這就是one_for_one。
在30秒內,給bank_center發送了3次normal_stop訊息,
給bank_center2發送了3次normal_stop訊息,
第六次發送normal_stop訊息之後,application: bank已經shutdown

3.2、測試transient重啟策略bank_sup:init/1中的permanent改為transient
Eshell V5.10.4 (abort with ^G)1> bank_center ! error.##[<0.38.0>bank_center:59] terminate: {bad_return_value,{ok,0}}error##[<0.40.0>bank_center:23] Start bank_center ...2> =ERROR REPORT==== 17-Jan-2015::17:09:15 ===** Generic server bank_center terminating ** Last message in was error** When Server state == 0** Reason for termination == ** {bad_return_value,{ok,0}}2> bank_center ! force_stop.##[<0.40.0>bank_center:59] terminate: "Force STOP"=ERROR REPORT==== 17-Jan-2015::17:09:28 ===** Generic server bank_center terminating ** Last message in was force_stop** When Server state == 0** Reason for termination == ** "Force STOP"force_stop##[<0.42.0>bank_center:23] Start bank_center ...3> 3> bank_center ! normal_stop.##[<0.42.0>bank_center:59] terminate: normalnormal_stop4> 4> whereis(bank_center). undefined5> supervisor:restart_child(bank_sup, center).##[<0.46.0>bank_center:23] Start bank_center ...{ok,<0.46.0>}6> whereis(bank_center). <0.46.0>7> bank_center ! shutdown. ##[<0.46.0>bank_center:59] terminate: shutdownshutdown8> whereis(bank_center). undefined9> supervisor:restart_child(bank_sup, center).##[<0.51.0>bank_center:23] Start bank_center ...{ok,<0.51.0>}10> whereis(bank_center). <0.51.0>11> bank_center ! {shutdown, test}. ##[<0.51.0>bank_center:59] terminate: {shutdown,test}{shutdown,test}12> whereis(bank_center). undefined

由上可見,進程退出的Reason為normal或shutdown或{shutdown, Term}時,bank_center不會被重啟,其他Reason時會被重啟。


4、完整示範代碼下載

地址:http://download.csdn.net/detail/u011471961/8371361

Erlang入門:構建application練習5(監督樹)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.