理解Erlang/OTP - Application

來源:互聯網
上載者:User

標籤:

http://www.cnblogs.com/me-sa/archive/2011/12/27/erlang0025.html 

1>application:start(log4erl).

    我們就從這一行命令開始說起吧,斷行符號之後可以把log4erl應用程式啟動起來.Erlang/OTP中的能完成特定功能集合的組件被稱為application. ,application是Erlang代碼和功能組織的形式之一([Erlang 0015]Erlang OTP設計原則).application的設計目的是通過運行一個或者多個進程來完成一定功能.為了能夠管理這些進程的生命週期,需要通過supervisor進行管理.

    application:start(log4erl).實際上是執行了application:start(log4erl,temporary).第二個參數表示應用程式的啟動類型(Start_Type).啟動類型還可以是permanent  transient,三種啟動類型的區別是:如果Start_Type==permanent 應用程式終止之後所有其它的應用程式和運行時系統都會死掉;如果Start_Type==transient 應用程式終止的原因是normal,這個訊息會報出來但是其它應用程式不會重啟,如果應用程式終止的原因不是normal,其他應用程式和運行時也會跟著死掉;如果Start_Type==temporary 應用程式死掉會報錯誤出來但是其它應用程式不受影響.注意實踐過程中很少使用transient參數,因為進程樹崩掉的時候,進程正常退出原因是shutdown不是normal,這個我之前的文章提到過:[Erlang 0017]Erlang/OTP基礎模組 proc_lib 無論使用哪種類型啟動,直接調用stop方法關閉application是不會影響到其它應用程式的.

    之前遇到過一個比較嚴重的問題導致應用崩掉,當時就有同事問為什麼erlang的進程還在,或者說運行時還活著?其實就是因為我們啟動應用程式的時候預設使用了temporary;

application設定檔
   application的設定檔(Application Resource File)基本上確定了application的格局.如果啟動失敗了就要檢查一下設定檔了,設定檔命名要求必須與application命名一致,即必須要有一個log4erl.app檔案:

 

{application, log4erl,
[{description, "Logger for erlang in the spirit of Log4J"},
{vsn, "0.9.0"},
{modules, [console_appender, %%該配置節可以留空 []
dummy_appender,
email_msg,
error_logger_log4erl_h,
% ................省略部分模組
xml_appender]},
{registered,[log4erl]}, %%這個應用程式將使用的註冊名
{applications, [kernel,stdlib]}, %%注意這個配置節是指定當前應用程式依賴哪些應用程式,類似Windows服務的依賴關係
{mod, {log4erl,[]}},
%{env,[{key,value},{k2,v2}]}, %env配置節,裡面以key-value的形式組織配置資料.可以用application:get_env/2讀取.
{start_phases, []}
]}.
   application啟動過程

 

   Erlang運行時啟動時,application controller進程會隨著Kernel應用程式啟動,在erlang shell中可以通過whereis(application_controller)找到它.應用程式相關的操作都由它來協調完成,它通過application模組暴露出來的介面來實現應用程式的載入,卸載,啟動,停止等等.

   應用程式啟動之前首先會進行載入load,如果沒有沒有載入application controller會首先執行load/1.載入完成猴子偶application controller會檢查application設定檔中的applications配置節中所列出的應用程式都已經在運行.如果有依賴項還沒有啟動,就拋出{error,{not_started,App}}的錯誤.

完成依賴項檢查之後application controller會為application建立application master.application master會成為該application中所有進程的Group Leader.(group leader決定了輸出重新導向的位置,參見這個問題:如何從A節點調用B節點的一個函數,結果輸出到B節點呢?) .通過設定檔的mod配置節,application master知道要調用回呼函數log4erl:start/2.

    application behavior有兩個回呼函數需要實現 start/2 stop/1分別來指定應用程式如何啟動,如何停止.啟動application的時候調用start方法通過啟動頂層的supervisor來建立進程樹.log4erl實現了application的behavior,它的start方法也是中規中矩的啟動了頂層superior:

 
start(_Type, []) ->    log4erl_sup:start_link(?DEFAULT_LOGGER). %%這裡?DEFAULT_LOGGER宏的值為default_logger
 

start對傳回值是有規格要求的:start(StartType, StartArgs) -> {ok, Pid} | {ok, Pid, State}

當返回結果不一致的時候應用程式自然啟動失敗,初學的時候最常見的錯誤就是加一下輸出看看是不是啟動了,結果就悲劇了.比如下面的代碼,start函數的傳回值是最後一個運算式io:format的值,而這個結果是ok,不符合application對start回呼函數結果的要求.

start(Startype,Arg) ->    demo_sup:start_link(),    io:format("demo app start").

 

application停止過程

   要停止application,application master首先會調用Module:prep_stop/1(如果存在),然後告知頂層的supervisor關閉(shutdown),shutdown的過程:整個監控樹的所有進程和包含的應用程式按照啟動的逆序終止.shutdown完成之後,application master調用Module:stop/1.最後application master自己終止掉.application停止了,但是依然處於已載入的狀態(loaded).

%log4erl stopstop(_State) ->    log_filter_codegen:reset(),    ok.
 

啟動 appmon:start()獲得更為直觀的印象.下面是log4erl應用程式進程的組織方式,log4erl_sup是log4erl application的頂層supervisor,上面的<0.42.0>和<0.43.0>按照上文的介紹應該是application master進程,我們通過取進程資訊來驗證:

 

   4> erlang:process_info(pid(0,42,0)).
[{current_function,{application_master,main_loop,2}},
{initial_call,{proc_lib,init_p,5}},
{status,waiting},
{message_queue_len,0},
{messages,[]},
{links,[<0.6.0>,<0.43.0>]},
{dictionary,[{‘$ancestors‘,[<0.41.0>]},
              {‘$initial_call‘,{application_master,init,4}}]},
{trap_exit,true},
{error_handler,error_handler},
{priority,normal},
{group_leader,<0.42.0>},
{total_heap_size,233},
{heap_size,233},
{stack_size,6},
{reductions,23},
{garbage_collection,[{min_bin_vheap_size,46368},
                      {min_heap_size,233},
                      {fullsweep_after,65535},
                      {minor_gcs,0}]},
{suspending,[]}]5> erlang:process_info(pid(0,43,0)).
[{current_function,{application_master,loop_it,4}},
{initial_call,{application_master,start_it,4}},
{status,waiting},
{message_queue_len,0},
{messages,[]},
{links,[<0.42.0>,<0.44.0>]},
{dictionary,[]},
{trap_exit,true},
{error_handler,error_handler},
{priority,normal},
{group_leader,<0.42.0>},
{total_heap_size,233},
{heap_size,233},
{stack_size,5},
{reductions,65},
{garbage_collection,[{min_bin_vheap_size,46368},
                      {min_heap_size,233},
                      {fullsweep_after,65535},
                      {minor_gcs,0}]},
{suspending,[]}] 6> application:stop(log4erl).ok

=INFO REPORT==== 27-Dec-2011::20:29:47 ===
    application: log4erl
    exited: stopped
    type: temporary
7> erlang:process_info(pid(0,43,0)).
undefined
8> erlang:process_info(pid(0,42,0)).
undefined
9> 今天先到這裡,晚安!   log4erl項目地址http://code.google.com/p/log4erl/

理解Erlang/OTP - Application

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.