我的個人博客網站雲諾說上線啦!所有文章都搬到新地址了,點擊圍觀吧!
問題: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
祝生活愉快!