1. 程式人生 > >erlang熱更新會kill掉程序嗎?

erlang熱更新會kill掉程序嗎?

問題:erlang熱更新會kill掉還在呼叫'old' 程式碼的程序嗎?

前幾天在跟人討論erlang模組熱更新時對方認為不會kill掉還在呼叫‘old’程式碼的程序,原因是這會破壞掉erlang的穩定性,這樣熱更也就完全沒有了意義!今天有時間我來寫這篇部落格驗證下。

大家都知道erlang VM為每個模組最多儲存2份程式碼,當前版本'current'和舊版本'old',當模組第一次被載入時,程式碼就是'current'版本。如果有新的程式碼被載入,'current'版本程式碼就變成了'old'版本,新的程式碼就成了'current'版本。erlang用兩個版本共存的方法來保證任何時候總有一個版本可用,對外服務就不會停止。

測試程式碼如下:

-module(test).
-compile(export_all).

start() ->
    Pid = spawn(fun() -> do_loop() end),
    register(?MODULE, Pid).
    
do_loop() ->
    receive
        Msg ->
            io:format("~p~n", [Msg])
    end,
    do_loop().

hot_update(Mod) ->
	code:purge(Mod),
	code:load_file(Mod).
測試結果如下:

從結果可以看出erlang熱更時會kill掉一直使用‘old’程式碼的程序,原因是如果程序一直在自己loop裡面,就會一直跑著‘old‘版本的程式碼, 那麼如何解決這個問題呢? 請接著看下面

程式碼修改如下:

-module(test).
-compile(export_all).

start() ->
    Pid = spawn(fun() -> do_loop() end),
    register(?MODULE, Pid).
    
do_loop() ->
    receive
        code_switch ->
            ?MODULE:do_loop();
        Msg ->
            io:format("~p~n", [Msg]),
            do_loop()
    end.
    

hot_update(Mod) ->
    code:purge(Mod),
    code:load_file(Mod).
測試結果如下:

在每次更新完之後給程序傳送一條code_switch訊息, 這樣就沒問題了,但是為什麼呢? 這就涉及到erlang函式內部呼叫和外部呼叫的問題了,詳細請參考下面幾篇文章:

http://blog.csdn.net/mycwq/article/details/43372687

http://blog.csdn.net/mycwq/article/details/41175237

http://erlang.org/doc/reference_manual/code_loading.html#id86381

http://learnyousomeerlang.com/designing-a-concurrent-application#hot-code-loving

祝生活愉快!