`
cwqcwk1
  • 浏览: 86871 次
文章分类
社区版块
存档分类
最新评论

再说说erlang的模块热更新

 
阅读更多

前面的文章有讲过erlang热更新,只是大概介绍,现在再深入一点讲erlang的模块热更新。erlang的热更新是模块级别的,就是一个模块一个模块更新的。

热更新是什么,就是在不停止系统的情况下对运行的代码进行替换。

如何进行热更新?

c(Mod) ->
	compile:file(Mod),
	code:purge(Mod),
	code:load_file(Mod).

以上就是shell c(Mod) 的主要代码,3个步骤:编译新的代码,清除旧代码,加载新代码

同样, l(Mod) 的主要代码如下,少了编译过程:

l(Mod) ->
	code:purge(Mod),
	code:load_file(Mod).

热更新原理

erlang文档有说明:

The code of a module can exist in two variants in a system: current and old. When a module is loaded into the system for the first time, the code becomes 'current'. If then a new instance of the module is loaded, the code of the previous instance becomes 'old' and the new instance becomes 'current'.

意思是,erlang每个模块都能保存2份代码,当前版本'current'和旧版本'old',当模块第一次被加载时,代码就是'current'版本。如果有新的代码被加载,'current'版本代码就变成了'old'版本,新的代码就成了'current'版本

这样,就算代码在热更新,有进程在调用这个模块,执行的代码也不会受影响。热更新后,这个进程执行的代码没有改变,只不过代码被标记成'old'版本。而新的进程调用这个模块时,只会访问'current'版本的代码。而'old'版本的代码如果没有进程再访问,就会在下次热更新被系统清除掉。

erlang用两个版本共存的方法来保证任何时候总有一个版本可用,这样,对外服务就不会停止。

热更新问题

有个问题,如果'old'版本一直都有进程在调用,在此期间,代码热再更新了会发生什么情况?

热更新时,如果模块存在'old'版本代码,erlang会kill掉所有调用这个'old'版本代码的进程,然后移除掉'old'版本代码,'current'版本变成了'old'版本,新的代码就成了'current'版本。

热更新问题重现

-module(t).
-compile(export_all).

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

结果如下:

7> t:start().
true
8> erlang:monitor(process, whereis(t)).  %%进程监控
#Ref<0.0.0.56>
9> whereis(t).
<0.40.0>
10> l(t).                                %%第1次热更
{module,t}
11> whereis(t).
<0.40.0>
12> l(t).                                %%第2次热更
{module,t}
13> whereis(t).
undefined
14> flush().
Shell got {'DOWN',#Ref<0.0.0.56>,process,<0.40.0>,killed}
ok
热更新2次后,进程就被kill掉了。(想知道在哪被kill,可在code_server中do_purge/3找到,参考[1])

解决热更新问题

如果进程一直在自己loop里面,就会一直跑着'old'版本的代码,这样的后果就是新的代码没有被使用,而且在下一次热更新时进程会被系统kill掉。

怎么解决这个问题,erlang文档还是能找到答案:

To change from old code to current code, a process must make a fully qualified function call. Example:

-module(m).
-export([loop/0]).

loop() ->
    receive
        code_switch ->
            m:loop();
        Msg ->
            do_something(),
            loop()
    end.

就是在热更新后,给这个进程发消息code_switch ,这样进程会调用 m:loop()

这里,loop()和m:loop()有什么区别呢?

erlang根据模块划分,函数分本地调用和外部调用,其中,本地调用是调用本模块内的函数,函数可以不导出,调用形式为Atom(Args);外部调用就是调用别的模块函数,函数必须导出,调用形式为Module:Function(Args).

在erlang VM中,进程调用模块的过程是先加载这个模块当前版本的代码再执行,如果进程一直都是本地调用,那么所有操作都是在进程当前运行的代码中完成。换句话,这个过程中进程不会去加载新的代码。打破这种局面的就是外部调用。


看这张图的时候先把绿色的内容去掉,进程就一直都是本地调用,加入绿色内容后,进程会重新加载这个模块的代码再运行。

那么有些同学会好奇,既然这样,erlang为何还要本地调用,直接全部都外部调用就好了?

1.外部调用的开销比本地调用大一点。外部调用时通过指针找到这个模块函数的导出地址,当模块热更时,就会修改这个指针指向的地址。内部调用是上下文跳转,对比少了一个指针查找,外加原子锁的开销。

2.外部调用的函数代码加载的时间稍微长一点,需要获取外部函数在导出函数表的地址,避免在执行时才去导出函数表查找函数地址造成开销。

今晚先到这里,有点困了,找时间再谈谈模块加载。 good night !


2015/7/11 修正外部调用和本地调用的的比较说明

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

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

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

分享到:
评论

相关推荐

    Erlang 中的Module级别热部署

    2. **获取旧版本信息**:在更新模块前,获取当前运行的旧版本的`Pids`(进程ID)和`Monitors`(监视器)。这可以使用`whereis/1`函数找到相关的进程,`sys:get_state/1`获取模块状态,以及`sys:change_code/4`进行...

    erlang两种参数模块化

    从给定的文件信息中,我们可以提炼出一些关于Erlang语言以及其参数化模块的重要知识点。 首先,Erlang是一种严格、动态类型的函数式编程语言。它的特点是没有破坏性更新,即数据不可变。Erlang内置了对并发的支持,...

    erlang代码热替换与应用部署

    代码热替换是Erlang的一大特色,它允许在不中断运行服务的情况下更新和替换正在运行的代码。这一特性使得Elang系统可以在不停止服务的情况下进行升级、修复bug或优化性能,极大地提高了系统的稳定性和可用性。 在...

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

    热代码替换是Erlang的一项核心特性,允许在不中断运行服务的情况下更新应用程序代码。它分为三个阶段:停止旧进程、加载新代码和启动新进程。 1. **加载新代码**:使用`code:load_file/1`或`code:replace/2`加载新...

    erlang 设计指南

    同时,BEAM还支持热代码替换,允许程序在运行时更新代码,而不会中断服务。 Erlang的模块化设计也是其强大的工具。模块是Erlang代码的基本组织单位,可以包含函数和记录。记录类似于结构体,提供了一种命名字段的...

    erlang 参考手册 模块部分--自己翻译的中文版

    Erlang是一种面向并发、分布式计算的编程语言,它的源代码是组织在模块(module)中的。模块是Erlang程序的基本单位,包含了特性(attribute)和函数(function)声明。下面将详细介绍Erlang模块的规则、特性、...

    英雄远征源码[erlang]

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

    erlang深度分析.pdf

    hotreplace模块允许代码热替换,不必重启节点即可更新模块。 #### 5. Erlang的分布式应用 Erlang的分布式应用通过VM间的消息传递进行交互。理解分布式协议(dist协议)的格式和全局数据结构(如ETS、Dets)的应用,...

    xiandiao_erlang_Erlang课后习题_

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

    erlang_版本24.3.4.4

    - **热升级**:Erlang支持在线代码升级,无需停机即可更新应用,保证服务的连续性。 - **错误处理**:Erlang采用异常处理机制,鼓励编写无副作用的纯函数,有助于编写容错性强的代码。 - **模式匹配**:Erlang的...

    erlang25.0 windows版本

    2. **API更新**:可能对Erlang的内置函数或模块进行增强,提供新的功能或修复已知问题。 3. **兼容性提升**:与先前版本相比,25.0可能增强了与其他软件或框架的兼容性。 4. **错误修复**:解决上一版本中的已知问题...

    erl-templates:Erlang 模块模板

    **Erlang 模块模板** 是一个针对 Erlang 编程语言的工具,它提供了一种方便的方式来创建和管理代码模板。Erlang 是一种并发性极强、功能丰富的编程语言,尤其适用于构建分布式系统和高可用性的软实时应用。在 Erlang...

    erlang9.rar

    Erlang语言的核心特点包括轻量级进程(Erlang中的进程与操作系统进程不同,它们更轻便且能快速切换)、模式匹配、函数式编程和热代码替换等。这些特性使得Erlang在处理高并发场景下表现出色,例如在电信、网络设备和...

    erlang编程 Introducing Erlang

    **Erlang编程:Introducing Erlang** Erlang是一种函数式编程语言,由爱立信在1986年开发,主要用于构建高可用性、容错性和并发性的分布式系统。"Introducing Erlang"是Simon St. Laurent撰写的一本入门级教程,...

    erlang 24.0版本 win64 位

    此外,Erlang的热更新(Code Loading)功能允许程序在运行时升级代码而无需停止服务。Erlang 24.0可能对这部分功能进行了优化,使得升级过程更加安全,减少了服务中断的风险。 在Windows 64位环境下,Erlang 24.0的...

    erlang中文基础教程

    模块名必须和文件名相同,否则 Erlang 无法找到模块。函数是模块中的基本单元,用于实现具体的计算任务。 在 Erlang 中,用户可以使用模块和函数来实现复杂的计算任务。例如,用户可以创建一个模块,定义一个函数来...

    erlang programming

    6. **热升级与无中断服务**:Erlang支持代码热升级,即在不中断运行的情况下更新应用程序代码,这对于保持高可用性和服务连续性至关重要。 7. **并发性能优化**:Erlang的并发性能优化涉及进程数量的控制、消息队列...

    erlang 程序设计 源码

    2. **故障恢复与容错**:Erlang支持热代码替换,可以在运行时更新代码而不会中断服务。此外,进程之间独立运行,一个进程的崩溃不会影响其他进程,这使得Erlang系统具有很高的容错性。 3. **函数式编程**:Erlang是...

Global site tag (gtag.js) - Google Analytics