- 浏览: 113366 次
文章分类
最新评论
-
norain2050:
AvinDev 写道@ccppasm2
触发一次后,队列长度依 ...
对Socket的{active, true}参数进行一些测试 -
cypherpunks:
$ javac *.java$ java LinkedList ...
Java 和 Erlang 的列表元素添加测试 -
langzhe:
“这样节点bar@192.168.0.3加载的模块都通过网络, ...
Boot Server 启动 -
mryufeng:
我重新做了测试http://mryufeng.iteye.co ...
一个简单的列表操作性能测试 -
mryufeng:
pg2狂依赖于global模块!
erlang module pg2
Java里面要实现Code Replacement,也就是什么热部署,通常是使用ClassLoader机制。不久前看到了一篇Google的Paper,里面讲解的C++代码热部署更为复杂。
在Erlang里面,实现Code Replacement其实很简单,最方便的方法可以参考 《Erlang Reference Manual》的12.3:
这种简单的HelloWorld例子,不能满足我的疑问。在一个更加复杂的应用里面,比如有多个Process,部分Process的代码更换后,其他没有更新的Process会怎样呢?下面做个试验。
实例代码:codereload.erl
程序里面有三个进程,一个Master和两个Worker,下面使用分布式进程通信来实现Code Replacement。
使用
启动erlang shell
启动codereload:
发一个"HI"过去看看:
嗯,收到了
好了,将源程序改一下:
这里改了版本号,还有注释掉发送给Pid2的更新通知
先编译新版本
发送更新通知:
收到了:
这时候master, Pid1, Pid2应该都是v0.2的版本,看看是不是这样:
OK,改成了 "0.2" 了,代码替换成功。事情还没有完,留意上面将 Pid2 ! refresh 给注释掉了么,这时候更新会怎样呢?先修改程序:
再次编译:
发送更新通知:
可见,现在只有Pid1收到了更新通知进行了更新,会产生怎样的结果呢:
噢,Pid2还停留在v0.2的代码上,可见各个进程的代码是独立的。
发送更新通知,让Pid2加载v0.3的代码:
这回Pid2更新到新版本了:
看到头晕了么?我也晕了,还有一种情况呢。在上面,
这步,如果不输入
而是再次编译:
发送个消息过去看看:
噢,怎么回事,is_process_alive(Pid2)返回false了,进程怎么挂了?
《Erlang Reference Manual》的12.3:
可见,Erlang里面,模块的代码只有新旧两个版本,当时Pid1对应于v0.3(Current),Pid2对应于v0.2(Old),当进行编译之后,Pid1的代码就是Old,而Pid2就被强制终止了。
对于以守护进程形式启动的Erlang进程,就不能在shell里面直接编译了,如果在外部编译,这个进程是不认的。我想到的一个方法就是使用rpc来调用编译:
rpc:call('foo@localhost', shell_default, c, [codereload]).
对于热部署,Erlang还有一种更强大的形式,就是使用OTP的Release Handling,我也不会,以后再学习了。
p.s:对本文有任何异议,欢迎拍板:)
在Erlang里面,实现Code Replacement其实很简单,最方便的方法可以参考 《Erlang Reference Manual》的12.3:
-module(m). -export([loop/0]). loop() -> receive code_switch -> m:loop(); Msg -> ... loop() end.
这种简单的HelloWorld例子,不能满足我的疑问。在一个更加复杂的应用里面,比如有多个Process,部分Process的代码更换后,其他没有更新的Process会怎样呢?下面做个试验。
实例代码:codereload.erl
-module(codereload). -export([main/0, master_loop/2, worker_loop/0]). -define(VERSION, "0.1"). main() -> process_flag(trap_exit, true), Pid1 = spawn(?MODULE, worker_loop, []), Pid2 = spawn(?MODULE, worker_loop, []), spawn(fun() -> register(master, self()), master_loop(Pid1, Pid2) end). master_loop(Pid1, Pid2) -> io:format("Pid1, Pid2 is alive ~p ~p~n",[is_process_alive(Pid1), is_process_alive(Pid2)]), receive refresh -> io:format("Master code reload~n"), Pid1 ! refresh, Pid2 ! refresh, codereload:master_loop(Pid1, Pid2); Any -> io:format("Master ~p receive message: ~p~n", [?VERSION, Any]), Pid1 ! Any, Pid2 ! Any, master_loop(Pid1, Pid2) end. worker_loop() -> receive refresh -> io:format("Worker code ~p reload~n", [self()]), codereload:worker_loop(); Any -> io:format("Worker ~p at ~p also receive message: ~p~n", [?VERSION, self(), Any]), worker_loop() end.
程序里面有三个进程,一个Master和两个Worker,下面使用分布式进程通信来实现Code Replacement。
使用
引用
erl -sname foo@localhost
erl -sname bar@localhost
erl -sname bar@localhost
启动erlang shell
启动codereload:
引用
(foo@localhost)1> codereload:main().
Pid1, Pid2 is alive true true
<0.39.0>
Pid1, Pid2 is alive true true
<0.39.0>
发一个"HI"过去看看:
引用
(bar@localhost)1> {master, 'foo@localhost'} ! "HI".
"HI"
"HI"
嗯,收到了
引用
(foo@localhost)2> Master "0.1" receive message: "HI"
(foo@localhost)2> Pid1, Pid2 is alive true true
(foo@localhost)2> Worker "0.1" at <0.37.0> also receive message: "HI"
(foo@localhost)2> Worker "0.1" at <0.38.0> also receive message: "HI"
(foo@localhost)2> Pid1, Pid2 is alive true true
(foo@localhost)2> Worker "0.1" at <0.37.0> also receive message: "HI"
(foo@localhost)2> Worker "0.1" at <0.38.0> also receive message: "HI"
好了,将源程序改一下:
-define(VERSION, "0.1"). --> -define(VERSION, "0.2").
Pid2 ! refresh, --> %Pid2 ! refresh,
这里改了版本号,还有注释掉发送给Pid2的更新通知
先编译新版本
引用
(foo@localhost)2> c(codereload).
{ok,codereload}
{ok,codereload}
发送更新通知:
引用
(bar@localhost)2> {master, 'foo@localhost'} ! refresh.
refresh
refresh
收到了:
引用
(foo@localhost)3> Master code reload
(foo@localhost)3> Worker code <0.37.0> reload
(foo@localhost)3> Worker code <0.38.0> reload
(foo@localhost)3> Pid1, Pid2 is alive true true
(foo@localhost)3> Worker code <0.37.0> reload
(foo@localhost)3> Worker code <0.38.0> reload
(foo@localhost)3> Pid1, Pid2 is alive true true
这时候master, Pid1, Pid2应该都是v0.2的版本,看看是不是这样:
引用
(bar@localhost)3> {master, 'foo@localhost'} ! "HI".
"HI"
"HI"
引用
(foo@localhost)3> Master "0.2" receive message: "HI"
(foo@localhost)3> Pid1, Pid2 is alive true true
(foo@localhost)3> Worker "0.2" at <0.37.0> also receive message: "HI"
(foo@localhost)3> Worker "0.2" at <0.38.0> also receive message: "HI"
(foo@localhost)3> Pid1, Pid2 is alive true true
(foo@localhost)3> Worker "0.2" at <0.37.0> also receive message: "HI"
(foo@localhost)3> Worker "0.2" at <0.38.0> also receive message: "HI"
OK,改成了 "0.2" 了,代码替换成功。事情还没有完,留意上面将 Pid2 ! refresh 给注释掉了么,这时候更新会怎样呢?先修改程序:
-define(VERSION, "0.2"). --> -define(VERSION, "0.3").
%Pid2 ! refresh, --> Pid2 ! refresh,
再次编译:
引用
(foo@localhost)3> c(codereload).
{ok,codereload}
{ok,codereload}
发送更新通知:
引用
(bar@localhost)7> {master, 'foo@localhost'} ! refresh.
refresh
refresh
引用
(foo@localhost)4> Master code reload
(foo@localhost)4> Worker code <0.37.0> reload
(foo@localhost)4> Pid1, Pid2 is alive true true
(foo@localhost)4> Worker code <0.37.0> reload
(foo@localhost)4> Pid1, Pid2 is alive true true
可见,现在只有Pid1收到了更新通知进行了更新,会产生怎样的结果呢:
引用
(bar@localhost)8> {master, 'foo@localhost'} ! "HI".
"HI"
"HI"
引用
(foo@localhost)4> Master "0.3" receive message: "HI"
(foo@localhost)4> Pid1, Pid2 is alive true true
(foo@localhost)4> Worker "0.3" at <0.37.0> also receive message: "HI"
(foo@localhost)4> Worker "0.2" at <0.38.0> also receive message: "HI"
(foo@localhost)4> Pid1, Pid2 is alive true true
(foo@localhost)4> Worker "0.3" at <0.37.0> also receive message: "HI"
(foo@localhost)4> Worker "0.2" at <0.38.0> also receive message: "HI"
噢,Pid2还停留在v0.2的代码上,可见各个进程的代码是独立的。
发送更新通知,让Pid2加载v0.3的代码:
引用
(bar@localhost)8> {master, 'foo@localhost'} ! refresh.
refresh
refresh
引用
(foo@localhost)4> Master code reload
(foo@localhost)4> Worker code <0.37.0> reload
(foo@localhost)4> Worker code <0.38.0> reload
(foo@localhost)4> Pid1, Pid2 is alive true true
(foo@localhost)4> Worker code <0.37.0> reload
(foo@localhost)4> Worker code <0.38.0> reload
(foo@localhost)4> Pid1, Pid2 is alive true true
这回Pid2更新到新版本了:
(bar@localhost)9> {master, 'foo@localhost'} ! "HI". "HI"
引用
(foo@localhost)4> Master "0.3" receive message: "HI"
(foo@localhost)4> Pid1, Pid2 is alive true true
(foo@localhost)4> Worker "0.3" at <0.37.0> also receive message: "HI"
(foo@localhost)4> Worker "0.3" at <0.38.0> also receive message: "HI"
(foo@localhost)4> Pid1, Pid2 is alive true true
(foo@localhost)4> Worker "0.3" at <0.37.0> also receive message: "HI"
(foo@localhost)4> Worker "0.3" at <0.38.0> also receive message: "HI"
看到头晕了么?我也晕了,还有一种情况呢。在上面,
引用
(foo@localhost)4> Master "0.3" receive message: "HI"
(foo@localhost)4> Pid1, Pid2 is alive true true
(foo@localhost)4> Worker "0.3" at <0.37.0> also receive message: "HI"
(foo@localhost)4> Worker "0.2" at <0.38.0> also receive message: "HI"
(foo@localhost)4> Pid1, Pid2 is alive true true
(foo@localhost)4> Worker "0.3" at <0.37.0> also receive message: "HI"
(foo@localhost)4> Worker "0.2" at <0.38.0> also receive message: "HI"
这步,如果不输入
引用
{master, 'foo@localhost'} ! refresh.
而是再次编译:
引用
(foo@localhost)4> c(codereload).
{ok,codereload}
{ok,codereload}
发送个消息过去看看:
(bar@localhost)9> {master, 'foo@localhost'} ! "HI". "HI"
引用
(foo@localhost)5> Master "0.3" receive message: "HI"
(foo@localhost)5> Pid1, Pid2 is alive true false
(foo@localhost)5> Worker "0.3" at <0.37.0> also receive message: "HI"
(foo@localhost)5> Pid1, Pid2 is alive true false
(foo@localhost)5> Worker "0.3" at <0.37.0> also receive message: "HI"
噢,怎么回事,is_process_alive(Pid2)返回false了,进程怎么挂了?
《Erlang Reference Manual》的12.3:
引用
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'.
Bot old and current code is valid, and may be evaluated concurrently. Fully qualified function calls always refer to current code. Old code may still be evaluated because of processes lingering in the old code.
If a third instance of the module is loaded, the code server will remove (purge) the old code and any processes lingering in it will be terminated. Then the third instance becomes 'current' and the previously current code becomes 'old'.
Bot old and current code is valid, and may be evaluated concurrently. Fully qualified function calls always refer to current code. Old code may still be evaluated because of processes lingering in the old code.
If a third instance of the module is loaded, the code server will remove (purge) the old code and any processes lingering in it will be terminated. Then the third instance becomes 'current' and the previously current code becomes 'old'.
可见,Erlang里面,模块的代码只有新旧两个版本,当时Pid1对应于v0.3(Current),Pid2对应于v0.2(Old),当进行编译之后,Pid1的代码就是Old,而Pid2就被强制终止了。
对于以守护进程形式启动的Erlang进程,就不能在shell里面直接编译了,如果在外部编译,这个进程是不认的。我想到的一个方法就是使用rpc来调用编译:
rpc:call('foo@localhost', shell_default, c, [codereload]).
对于热部署,Erlang还有一种更强大的形式,就是使用OTP的Release Handling,我也不会,以后再学习了。
p.s:对本文有任何异议,欢迎拍板:)
发表评论
-
关于那本书的视频访谈
2008-11-07 21:43 2533应ZDNet的邀请,《Erlang程序设计》的译者赵东炜老 ... -
Nitrogen - Yet Another Web Framework
2008-10-27 22:52 1688这是火星旧闻了,在若干天之前,有位大佬在maillist宣告了 ... -
New Erlang book
2008-08-21 13:00 2077Manning 出版社发布了最新的Erlang书籍《Con ... -
Erlang R12B3 的sub binary优化似乎有Bug?
2008-06-28 13:20 230409.3.18更新: 随着R13A release,我也重新查 ... -
[笔记]Erlang R12B中的sub binary优化
2008-06-28 11:29 1761在Erlang的 DOC erl5.6.3/doc/effic ... -
一种简单的UUID生成方法
2008-06-07 00:53 4396maillist有人提供了一种简单的UUID生成方法: 引用 ... -
[笔记]用ets实现了把一致性哈希中的最接近项查找
2008-04-01 23:39 3185最近有些空,继续捣鼓consisten hash的简单实现。先 ... -
Big Endian & Little Endian 笔记
2008-03-13 22:43 2950突然想做IP库的解析,用Erlang,自然就碰到了Big En ... -
小测试:两种构造字符串方式的性能对比
2008-03-05 23:30 2863先推荐两篇文章: http://www.wagerlabs.c ... -
对Socket的{active, true}参数进行一些测试
2008-03-02 22:39 6087以前不是很了解Erlang网络编程中流量控制,现在做一下笔记。 ... -
高阶函数中变量的绑定和匹配问题
2007-10-07 14:40 1806一直一来没有留意到这个问题,今天偶尔在blog上看到,就标记一 ... -
Java 和 Erlang 的列表元素添加测试
2007-08-07 12:09 2789maillist上面对 “VM & BEAM Spec ... -
对Erlang R11B-5 ssl库的修正
2007-07-20 20:41 2257http://www.trapexit.org/index.p ... -
读 Programming Erlang
2007-07-17 12:21 3479《Programming Erlang》Joe的新书,买了个电 ... -
修正Socket Base Distribution一节实例代码的Bug
2007-07-14 01:27 3125拿到了Programming Erlang的电子书,研究一下P ... -
Boot Server 启动
2007-07-11 14:01 3683如何让多台Server上的Erlang进程启动时只加载远程服务 ... -
设置Erlang节点的监听端口范围
2007-07-05 17:55 2877是个Undocument的Flags,记录一下: erl - ... -
CEAN 1.3 的 iconv 模块可用了
2007-07-05 16:44 2180CEAN1.3出来了,试试那个iconv还能不能用,在Wind ... -
一个简单的列表操作性能测试
2007-05-24 12:12 3128Note:首先要了解,Erlang里面的列表,比如 [1,2, ... -
用Erlang写了个解八数码的小程序
2007-05-21 21:50 2120NOTE:修正了一个Bug,加入了能否求解的数学算法判断,代码 ...
相关推荐
本篇将深入探讨Erlang应用的部署与热代码替换。 一、Erlang应用部署 在Erlang环境中,应用通常被打包成一个`.app`文件,包含应用元数据,以及一个或多个beam文件(编译后的Erlang代码)。部署Erlang应用的步骤如下...
本文将深入探讨Erlang中的代码热替换(Code Replacement)技术及其在应用部署中的重要性。 代码热替换是Erlang的一大特色,它允许在不中断运行服务的情况下更新和替换正在运行的代码。这一特性使得Elang系统可以在...
在Erlang Shell中,使用`c(module_name).`命令编译指定的模块,如`c(tut).`。若编译成功,会返回`{ok,module_name}`的信息;若编译失败,系统会给出错误报告,帮助开发者定位并修正问题。 通过以上介绍,我们可以...
Erlang并发编程,Erlang程序设计,Erlang中文手册。 学习erlang的好资料。 Erlang是一个结构化,动态类型编程语言,内建并行计算支持。最初是由爱立信专门为通信应用设计的,比如控制交换机或者变换协议等,因此...
用户可以在 Erlang Shell 中输入命令,例如数学运算符号,函数调用等。Erlang Shell 提供了一个交互式的环境,用户可以实时查看输出结果。 2. 顺序编程 顺序编程是 Erlang 编程语言的基础,用户可以使用 Erlang ...
本书不适用于初学者。从大多数教程、书籍以及培训课程上所学到的知识,还不能用来运维、 诊断以及调试生产环境中的Erlang 系统。在程序员学习新的语言和环境时,...道一些如何在生产环境中部署Erlang的最佳实践F 18 F。
- **1.3.1 进程**:Erlang的进程与其他语言中的线程类似,但它们是轻量级的,并且通过消息传递进行通信。 - **1.3.2 信息传递**:进程间通信是通过消息传递完成的,Erlang提供了简单的机制来实现这一点。 - **1.3.3 ...
标题中的“<27>erlang record”可能指的是Erlang编程语言中的Record特性,它是一种数据结构,类似于结构体或者哈希表,用于组织和操作数据。在Erlang中,Record提供了一种方便的方式来定义和访问具有固定字段的数据...
在Erlang中,这个模块可以帮助开发者高效地存储和检索数据,同时在内存资源紧张时自动清理过期或不常访问的数据。 在Erlang LRU Cache模块中,主要有以下几个关键概念和功能: 1. **键值对(Key-Value Pair)**:...
2. **分布式Erlang**:如何在多台机器上部署和管理Erlang集群,实现跨节点的进程通信。 3. **行为模式**:如GenServer、GenEvent和Supervisor,它们提供了一种组织和管理Erlang进程的标准方式。 4. **性能优化**:...
在IT行业中,Erlang是一种强大的并发编程语言,主要用于构建高可用性、容错性和分布式系统。当我们在处理中文字符时,特别是在Erlang环境中,可能会遇到“中文乱码”的问题。这个问题通常与字符编码、文件读写以及...
以上总结了Erlang深度分析的主要知识点,涵盖了虚拟机、性能分析、编码实践、分布式系统开发、内存管理、高可用性设计、网络通信、热部署、并发模型、本地接口设计、系统监控以及社区资源等多个方面。这些知识能够...
Erlang中的链接(Linking)和监控(Monitoring)机制允许进程间建立关系,以便在另一进程崩溃时得到通知。链接用于追踪相关进程的状态,而监控则可以观察进程的生存状态。 ### 5. 消息传递 Erlang的进程间通信主要...
Erlang术语部分提到了Erlang程序的模块化设计,强调了模块(module)、函数(function)和进程(process)的基本概念。模块是Erlang程序中代码封装的基本单位,其中函数是执行操作的最小单元。模块包含的函数数量不宜过多...
在Erlang编程语言中,DNS(Domain Name System)解析是一项关键功能,它允许程序将域名转换为IP地址,反之亦然。Erlang提供了强大的工具来处理网络通信,包括DNS解析。这篇博客(虽然链接不可用)可能讨论了如何在...