`
jzhihui
  • 浏览: 268137 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

Erlang热部署 – 模块更新

阅读更多

Erlang的热部署做的很完善,参见Release Handling,这篇文章只关心最基本的模块更新。模块是Erlang程序组织的最基本单元。如下代码就是一个最简单的hello模块(为了说明问题,我们添加了一个init函数):

 

-module(hello).
-export([init/0, hello/1]).

init() ->
    Db = dict:new(),
    dict:store(name, "jzh", Db).

hello(Db) ->
    Value = dict:fetch(name, Db),
io:format("hello: ~p!~n", [Value]).

 

 运行一下:

 

1> c(hello).
{ok,hello}
2> Db = hello:init().
{dict,1,16,16,8,80,48,
      {[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]}
      {{[],[],[],[],[],
        [[name,106,122,104]],
        [],[],[],[],[],[],[],[],[],[]}}}
3> hello:hello(Db).
hello: "jzh"!
ok

 c命令的作用是编译和加载指定模块)

 

hello:hello打印出hello的字样,但是,假如我们现在希望输出hi,而不是hello,要怎么做呢?Java里面一般需要重新编译和运行程序,但是先前的运行状态也会丢失(dict中存储的name),需要重新运行init方法。

我们将hello改成hi,并在同一个控制台直接调用hello:hello(未调用hello:init),看看结果是怎么样的:

 

4> c(hello).
{ok,hello}
5> hello:hello(Db).
hi: "jzh"!
ok

 可以看到,代码更新后打印出hi字样(保存在dict中的name,并没有因为新代码的加载而失效)。

 

 

         从上面的示例可以看到,Erlang可以在运行时进行代码的替换,而不会影响到运行时状态(数据)。在Java中要完成类似的功能比较难,那Erlang背后实现这种功能的原理是什么呢?原来,在任何时候,一个模块都可以有两个版本加载到运行时系统,一个旧版本,一个当前版本。在加载一个模块时,运行时系统会先检查这个模块是否已经有一份代码存在,如果存在,则把已存在的代码作为旧的代码,新加载的代码作为当前版本。如果有第三份代码加载进系统,则原来的旧版本代码会被清理掉,跟此版本代码相关的所有进程都会被结束;原来的当前代码变为当前的旧版本代码,第三份代码成为当前版本。

 

         函数调用有两种方式:一种完全限定调用(Mod:Func),包括模块内、模块之间这种方式的调用,以及模块之间通过import指令导入其它模块,再直接通过函数名调用;一种直接调用(Func),只存在于模块内的函数调用。完全限定的函数调用总是引用当前版本代码。旧版本代码只可能通过直接调用的方式引用到。

 

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

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

 如上代码,如果有代码更新,并且进程没有收到code_switch消息,那么进程就会通过loop调用一直在引用旧版本代码;而收到code_switch消息后,进程便通过m:loop引用到当前版本代码。

 

(这一块,《Erlang编程指南》软件升级一章,幕后一节对原理讲的有点复杂)

 

从虚拟机实现角度来看,这两者的区别在哪里呢?看一下如下代码:

 

-module(test).
-import(hello, [hello/0]).

test2() ->
	ok.

test() ->
	test2(),
	test:test2(),
	hello(),
	hello:hello(),
	ok.

 

 我们来看看test函数生成的opcode

 

i_call_f test:test2/0
i_call_ext_e test:test2/0
i_call_ext_e hello: hello/0
i_call_ext_e hello: hello/0

可以看出,直接调用test2生成的opcodei_call_f,而其它的全限定调用(包括hello()调用)都生成的是i_call_ext_e指令。这两者有什么区别?i_call_f指令会直接跳到相应函数的入口(进程生成后,地址确定)并执行,而i_call_ext_e会根据模块导出函数列表中的地址跳转(详见[$OTP_SRC/erts/emulator/beam/beam_emu.c --> process_main)。这个地址在模块更新时会更新为当前版本代码导出函数的地址(详见[$OTP_SRC/erts/emulator/beam/beam_bif_load.c --> load_module_2] ,导出函数地址通过[$OTP_SRC/erts/emulator/beam/export.h]Export结构的address定义)。从这里也可以看出来,除非有进程在引用旧版本的代码,模块更新后,其它进程是无法再通过任何方式引用到旧版本的代码(模块导出函数列表中的地址已更新)。

 

0
0
分享到:
评论

相关推荐

    Erlang 中的Module级别热部署

    Erlang 的热部署是基于其模块化的设计思想实现的。每个Erlang程序由一个或多个模块组成,这些模块定义了函数和数据类型。当需要更新代码时,Erlang允许我们重新编译并加载新的模块版本,而不必重启整个应用程序。 ...

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

    3. **部署到节点**:将释放包复制到目标Erlang节点的`ebin`目录下,或者使用`release_handler`模块的`add_application/2`或`install_release/1`函数进行远程部署。 4. **启动应用**:调用`application:start/1`或`...

    erlang两种参数模块化

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

    erlang代码热替换与应用部署

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

    搭建自己的erlang服务器(基于RabbitMQ改进)(一)

    例如,如果你想要添加一个新功能,可以在`rabbitmq_server/src`目录下创建一个新的Erlang模块,然后在`rabbit`模块中调用它。确保遵循Erlang的模块命名规范,并在`rabbit.app`配置文件中声明你的模块。 在测试和...

    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)的应用,...

    erlang9.rar

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

    erlang25.0 windows版本

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

    erlang中文基础教程

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

    erlang_版本24.3.4.4

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

    xiandiao_erlang_Erlang课后习题_

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

    erlang编程 Introducing Erlang

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

    erlang 深度分析

    Erlang Driver和热部署 - **Driver**: 一种特殊类型的Port,用于与操作系统直接交互。 - **热部署**: - **概念**: 不重启服务即可更新代码的能力。 - **实现**: 利用Erlang的代码加载机制实现。 - **应用场景**: ...

    erlang 程序设计 源码

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

    erlang 部分源码

    Erlang支持在运行时更新和替换代码,而无需停止系统。这部分源码将展示如何实现这种强大的功能。 8. **分布式特性** Erlang天生支持分布式计算,源码中可能会涉及节点间的通信协议和集群管理。 9. **IO系统** ...

Global site tag (gtag.js) - Google Analytics