`
litaocheng
  • 浏览: 337668 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

再谈Erlang代码热替换

阅读更多
Erlang一个非常值得称道的特性就是代码热替换(Hot Code Sawpping),我们在调用函数时,通过M:F(A)的方式,可以保证总是加载最新的代码。

在《Erlang程序设计》中E4部分,通过一个小例子展示了代码的动态加载,两个module代码如下:
a.erl
-module(a).
-compile(export_all).
-import(b, [x/0]).

start(Tag) ->
    spawn(fun() -> loop(Tag) end).
    
loop(Tag) ->
    timer:sleep(3000),
    Val = x(),
    io:format("Vsn1 (~p) b:x() = ~p~n", [Tag, Val]),
    loop(Tag).   


b.erl
-module(b).
-compile(export_all).

x() -> 1.


这个例子中是通过c(a), c(b)的方式编译修改后的a.erl 和 b.erl,这里其实是做了两件事:
1,编译module
2,load module
所以我们在这个例子中,可以看到如果我们修改了b的代码,然后在Erlang shell中通过:
c(b). 我们可以立即看到“新”的b module在运行了。

在Erlang中每个Module可以保存2个version,如果再有第三个version加入,那么首先要通过code:purse/1清理先前的版本,随后才可以load新的module。
在Erlang内部,当有新的Module被调用时,旧的Module的Export 函数将被新的Export函数代替,因此当我们实用M:F(A)的方式调用函数时,将调用最新代码。

让我们启动a module:
> a:start(one).
Vsn1 (one) b:x() = 1


随后我们修改a.erl:
-io:format("Vsn1 (~p) b:x() = ~p~n", [Tag, Val]),
+io:format("Vsn2 (~p) b:x() = ~p~n", [Tag, Val]),

然后编译a.erl:
$ erlc a.erl

当前,在Erlang中只有Vsn1版本的a,回到erlang shell中,加载Vsn2:
> code:load_file(a).

现在在Erlang中有Vsn1和Vsn2两个版本的a module。
我们在启动一个新的a process:
> a:start(two).
Vsn2 (two) b:x() =1


好了让我们再次修改a.erl:
-io:format("Vsn2 (~p) b:x() = ~p~n", [Tag, Val]),
+io:format("Vsn3 (~p) b:x() = ~p~n", [Tag, Val]),

然后编译a.erl:
$ erlc a.erl

注意:此时Erlang shell中并没有加载Vsn3版本的代码,因为我们没有使用c(a)的方式编译加载a module。我们可以测试一下:
>a:start(three).
<0.38.0>
Vsn2 (three) b:x() = 1

毫无疑问,还是Vsn2

接下来我们想加载Vsn3版本的a,回到Erlang shell:
> code:load_file(a).
=ERROR REPORT==== 14-Jan-2009::23:16:23 ===
Loading of /home/litao/erl/a.beam failed: not_purged
{error,not_purged}

=ERROR REPORT==== 14-Jan-2009::23:16:23 ===
Module a must be purged before loading

oh,产生了一个错误信息,返回{error,not_purged},现在已经有Vsn1,Vsn2两个a module了,这第三个被拒绝了。我们必须调用code:purge/1清除Vsn1:
> code:purge(a).
true
Vsn2 (three) b:x() = 1
Vsn2 (two) b:x() = 1

返回true,同时Vsn1版本的a process已经被kill了,现在只有Vsn2了。接下来加载我们的Vsn3吧:
> code:load_file(a).
{module,a}
Vsn2 (two) b:x() = 1
Vsn2 (three) b:x() = 1
8> a:start(five).
<0.43.0>
Vsn2 (three) b:x() = 1
Vsn2 (two) b:x() = 1
Vsn3 (five) b:x() = 1

好了Vsn2成了旧版本,Vsn3成了新版本。
自己动手实验一下吧!

Update:
code:soft_purge(Module),如果没有process运行旧的Module,则返回true(表明此Module可以被温和的purge);否则返回false。
可以通过erlang:check_process_code(Pid, Module)检测Process是否运行某个Module的Old version,这个检测不会检测process的运行时,判断当前函数是否为old
请注意:code:purge 和 code:soft_purge 针对的是old version,如果当前module只有一个version,那么 purge返回false, soft_purge返回true.


分享到:
评论
3 楼 pascal4123 2009-02-24  
好文字.


litaocheng 写道
Erlang一个非常值得称道的特性就是代码热替换(Hot Code Sawpping),我们在调用函数时,通过M:F(A)的方式,可以保证总是加载最新的代码。

在《Erlang程序设计》中E4部分,通过一个小例子展示了代码的动态加载,两个module代码如下:
a.erl
-module(a).
-compile(export_all).
-import(b, [x/0]).

start(Tag) ->
    spawn(fun() -> loop(Tag) end).
    
loop(Tag) ->
    timer:sleep(3000),
    Val = x(),
    io:format("Vsn1 (~p) b:x() = ~p~n", [Tag, Val]),
    loop(Tag).   


b.erl
-module(b).
-compile(export_all).

x() -> 1.


这个例子中是通过c(a), c(b)的方式编译修改后的a.erl 和 b.erl,这里其实是做了两件事:
1,编译module
2,load module
所以我们在这个例子中,可以看到如果我们修改了b的代码,然后在Erlang shell中通过:
c(b). 我们可以立即看到“新”的b module在运行了。

在Erlang中每个Module可以保存2个version,如果再有第三个version加入,那么首先要通过code:purse/1清理先前的版本,随后才可以load新的module。
在Erlang内部,当有新的Module被调用时,旧的Module的Export 函数将被新的Export函数代替,因此当我们实用M:F(A)的方式调用函数时,将调用最新代码。

让我们启动a module:
> a:start(one).
Vsn1 (one) b:x() = 1


随后我们修改a.erl:
-io:format("Vsn1 (~p) b:x() = ~p~n", [Tag, Val]),
+io:format("Vsn2 (~p) b:x() = ~p~n", [Tag, Val]),

然后编译a.erl:
$ erlc a.erl

当前,在Erlang中只有Vsn1版本的a,回到erlang shell中,加载Vsn2:
> code:load_file(a).

现在在Erlang中有Vsn1和Vsn2两个版本的a module。
我们在启动一个新的a process:
> a:start(two).
Vsn2 (two) b:x() =1


好了让我们再次修改a.erl:
-io:format("Vsn2 (~p) b:x() = ~p~n", [Tag, Val]),
+io:format("Vsn3 (~p) b:x() = ~p~n", [Tag, Val]),

然后编译a.erl:
$ erlc a.erl

注意:此时Erlang shell中并没有加载Vsn3版本的代码,因为我们没有使用c(a)的方式编译加载a module。我们可以测试一下:
>a:start(three).
<0.38.0>
Vsn2 (three) b:x() = 1

毫无疑问,还是Vsn2

接下来我们想加载Vsn3版本的a,回到Erlang shell:
> code:load_file(a).
=ERROR REPORT==== 14-Jan-2009::23:16:23 ===
Loading of /home/litao/erl/a.beam failed: not_purged
{error,not_purged}

=ERROR REPORT==== 14-Jan-2009::23:16:23 ===
Module a must be purged before loading

oh,产生了一个错误信息,返回{error,not_purged},现在已经有Vsn1,Vsn2两个a module了,这第三个被拒绝了。我们必须调用code:purge/1清除Vsn1:
> code:purge(a).
true
Vsn2 (three) b:x() = 1
Vsn2 (two) b:x() = 1

返回true,同时Vsn1版本的a process已经被kill了,现在只有Vsn2了。接下来加载我们的Vsn3吧:
> code:load_file(a).
{module,a}
Vsn2 (two) b:x() = 1
Vsn2 (three) b:x() = 1
8> a:start(five).
<0.43.0>
Vsn2 (three) b:x() = 1
Vsn2 (two) b:x() = 1
Vsn3 (five) b:x() = 1

好了Vsn2成了旧版本,Vsn3成了新版本。
自己动手实验一下吧!






2 楼 mryufeng 2009-01-16  
可以再研究下动态库模块代码热替换!
1 楼 tooor 2009-01-15  
恩, 又加深一遍印象, 加油

相关推荐

    erlang代码热替换与应用部署

    `optc.tar.gz`和`otp_code_change_avi.rar`这两个文件可能包含了关于Erlang代码热替换的实例代码或演示视频。`optc.tar.gz`可能是一个Erlang应用的释放包,包含了多个版本的源码和相关的配置文件。而`otp_code_...

    Erlang应用部署与热代码替换--理解2

    在Erlang环境中,应用通常被打包成一个`.app`文件,包含应用元数据,以及一个或多个beam文件(编译后的Erlang代码)。部署Erlang应用的步骤如下: 1. **编译源代码**:使用`erlc`命令将Erlang源代码编译为beam文件...

    Erlang 中的Module级别热部署

    在Erlang编程环境中,模块级别的热部署是一项关键特性,它允许开发者在不中断系统运行的情况下更新或替换已加载的模块。这对于实时系统和高可用性服务尤其重要,因为它们需要持续提供服务而不能因为代码更新而停机。...

    远古封神+英雄远征的ERLANG游戏服务器代码

    《远古封神》与《英雄远征》是两款受欢迎的网络游戏,它们的后端服务器采用了ERLANG这一编程语言来构建。ERLANG是一种为并发、分布式和容错系统设计的函数式编程语言,因其在实时系统和大规模并发处理中的优秀性能而...

    erlang并发编程实战源代码

    erlang并发编程实战源代码erlang并发编程实战源代码

    Erlang程序设计].源代码

    这些源代码可能是书中实例的实现,或者是针对Erlang编程技巧和概念的示例。通过阅读和分析这些源代码,你可以深入理解Erlang的关键特性: 1. 函数式编程:Erlang是一种纯函数式语言,这意味着函数没有副作用,相同...

    Erlang程序设计及源代码打包

    5. **热代码替换**:Erlang允许在运行时更新代码,无需停止服务,这对于维护和升级系统非常有利。 **随书源代码分析** `jaerlang-code.zip`文件包含了书中示例代码,这些代码可以帮助读者更好地理解书中的概念。...

    [Erlang程序设计]源代码

    **Erlang程序设计源代码详解** Erlang是一种面向并发、函数式编程语言,尤其在分布式系统和高可用性领域表现出色。本资源包含了《Erlang程序设计》一书的所有实例代码,旨在帮助读者深入理解Erlang语言的核心特性和...

    Erlang程序设计第2版附书代码

    3. **模块和函数**:Erlang代码组织成模块,每个模块可以包含多个函数。书中可能包含模块定义和函数定义的示例。 4. **错误处理**:通过代码示例,你可以学习如何优雅地处理错误,比如使用`try...catch...after`...

    二郎助手erlang开发工具、erlang编辑器

    二郎助手的核心特性在于其全面的Erlang支持,包括语法高亮、代码自动完成、错误检查和调试功能。作为一个基于VS2005开发的项目,它继承了Visual Studio家族的强大编辑器功能,并且针对Erlang语言进行了优化。这意味...

    改进erlang版的protobuf代码

    5. **编译工具链改进**:可能是对protobuf编译器的Erlang绑定进行了优化,使得生成的Erlang代码更加高效或者易于使用。 配套的文章地址(http://blog.csdn.net/mycwq/article/details/42122439)可能提供了更多关于...

    erlang深度分析.pdf

    BEAM是Erlang的字节码解释器,模拟器可以用于开发阶段模拟运行和测试Erlang代码,有助于调试程序和优化性能。 #### 7. 内存管理 Erlang的内存管理是非常高效的,它使用了一种特殊的垃圾回收机制来确保低延迟。了解...

    for_each_file 用erlang代码实现遍历文件

    在上述代码中,`for_each_file/2`首先列出目录中的所有文件,然后对每个文件调用`process_files/3`。`process_files/3`会打开每个文件,读取其内容,并对每一行调用`Callback`。当遇到错误或文件末尾时,它会关闭...

    erlang 部分源码

    Erlang是一种面向并发的、动态类型的编程语言,主要用于...通过深入研究这个压缩包中的源代码,开发者可以获得对Erlang语言核心机制的深入理解,这对于优化Erlang代码、调试问题或开发新的Erlang工具都是宝贵的资源。

    英雄远征源码[erlang]

    Erlang的热代码升级机制允许在不中断服务的情况下更新代码,这对于在线游戏至关重要,因为它保证了游戏的持续运行,同时允许开发者进行快速迭代和修复。 6. **错误处理与容错** Erlang的错误处理机制强调“失败早...

    KMP(Erlang)代码实现

    由于部分内容中存在OCR扫描错误,但整体上代码逻辑清晰,我们能够理解其算法实现的要点,以及如何利用Erlang的特性来编写高效的字符串匹配算法。这种语言的函数式编程风格使得代码具有很好的可读性和易理解性。在...

    Erlang程序设计及源码

    函数式编程的特性使Erlang代码更易于理解和调试,因为它们通常没有副作用,这在并行计算中尤为重要。 3. **错误处理与容错** Erlang采用“let it crash”哲学,即系统中出现问题时,允许错误的进程崩溃,然后由...

    xiandiao_erlang_Erlang课后习题_

    3. **热代码更新**:Erlang支持运行时代码替换,无需停止服务即可更新和修复应用程序,这在实时系统中非常有用。 4. **容错性**:Erlang的进程模型鼓励设计出可以失败并从中恢复的系统。当一个进程出错时,它不会...

    erlang 16b03 source

    Erlang是一种函数式编程语言,以其并发能力、热代码替换和故障隔离特性而著名。R16B03是OTP的迭代版本,它可能包含了性能优化、错误修复、新功能以及对现有组件的改进。源代码的获取允许开发者深入理解Erlang的内部...

Global site tag (gtag.js) - Google Analytics