Erlang中的代码重新加载是否仅限于两个版本?

Erlang中的代码重新加载是否仅限于两个版本?,erlang,real-time,upgrade,otp,on-the-fly,Erlang,Real Time,Upgrade,Otp,On The Fly,然而,没有明确宣传的是,显然,在删除尚未有机会将执行代码路径从旧路径切换到新路径的现有连接之前,您只能进行一次无缝重新加载 确实如此,还是Erlang/OTP有一个额外的高级代码重新加载功能,可以避免在执行第二次代码重新加载时删除上一代的执行代码路径?()2个版本。为了说明这种行为,我使用了小模块: -module (tver). -compile([export_all]). start(Name) -> Pid = spawn(?MODULE,loop,[]), r

然而,没有明确宣传的是,显然,在删除尚未有机会将执行代码路径从旧路径切换到新路径的现有连接之前,您只能进行一次无缝重新加载


确实如此,还是Erlang/OTP有一个额外的高级代码重新加载功能,可以避免在执行第二次代码重新加载时删除上一代的执行代码路径?()

2个版本。为了说明这种行为,我使用了小模块:

-module (tver).

-compile([export_all]).

start(Name) ->
    Pid = spawn(?MODULE,loop,[]),
    register(Name,Pid).

loop() ->
    receive
        % an internal call won't reload the code. The process keeps
        % executing the current version 
        version -> io:format("version 1~n"), loop();
        % an external call will reload the code. The process will use
        % the new version if any available in the VM. Notes that it
        % will not search in the path if a new version exists!
        update -> io:format("update code~n"), ?MODULE:loop();
        stop -> io:format("bye...~n")
    end.
当我更改版本时,我更改打印的字符串。现在,版本管理正在运行:

Erlang/OTP 18 [erts-7.0] [64-bit] [smp:4:4] [async-threads:10]

Eshell V7.0  (abort with ^G)
1> c(tver).
{ok,tver}
2> tver:start(v1).
true
3> v1 ! version.
version 1
version
4> whereis(v1).
<0.39.0>
检查v1进程是否仍在执行版本1

6> v1 ! version.   
version 1
version
7> whereis(v1).    
<0.39.0>
外部调用强制使用新版本。在现实生活中,你应该做一些验证,比如什么是旧版本,什么是新版本,升级是否可能,是否有一些数据需要调整

11> v1 ! update. 
update code
update
12> v1 ! version.
version 2
version
13> v2 ! version.
version 2
version
14> whereis(v1).   
<0.39.0>
15> whereis(v2). 
<0.50.0>
n-2版本已经不存在了!进程V1和V2已经死亡,尽管它们只是在等待接收块。在真正的OTP系统中,他们的主管会根据他们的重启策略重启他们

28> tver:start(v4).                                           
true
29> whereis(v3).                            
<0.69.0>
30> whereis(v4).
<0.80.0>

是的,一次只能运行一个模块的两个版本。但是,您可以编写代码,在为一个连接提供服务时,将代码切换到新代码。

是的,只有两个版本。但是你可以告诉代码加载器你想要什么版本,检查未迁移的代码,回滚等等。您可以通过OTP向前迁移正在运行的进程(包括它们所持有的任何套接字),或者通过您需要自己编写的等效函数。这需要计划和思考。Erlang是唯一能够做到这一点的运行时之一,但它并不是免费提供的——它需要开发人员付出努力。为了澄清这一点:在完美的答案中,您将展示这个问题上可能的解决方法——2013年的jaerlang2书中已经出现了一个例子,即只有两个版本同时运行,但是书中没有讨论过如何解决这个问题。@zxq9,很好的评论,你应该把它作为一个答案;一些可能的代码引用说明实际的Erlang应用程序是否会遇到这样做的麻烦,这也是一件好事。我想我更多的是寻找一个答案,说明在这个问题上可能的解决方法——2013年的jaerlang2书中已经出现了一个例子,即只有两个版本同时运行,但是书中没有讨论如何解决这个问题。@cnst:上面的例子展示了如何管理代码的演变:我不知道在一个VM中运行一个模块的两个以上版本的可能性,但是第一部分显示了(在一个简单的例子中)如何将运行的代码从一个版本升级到另一个版本。OTP提供特定的回调来管理代码升级或降级。虽然在生产系统中一次进行一次进化已经非常棘手,但我会拒绝任何要求进行更多进化的请求。我会在我的答案中添加一些解释。你知道在野外出现这样的代码有多普遍吗?例如,ejabberd或riak或您选择的其他流行应用程序是否实现了这些功能?有没有像这样需要额外做多少工作的例子?@cnst:gen_*OTP行为学对此有支持。因此,基本上你可以轻松地完成它。但差别不大。通常的方法是冻结应用程序,升级,然后继续,这使得它更容易控制。但所有这些都可以在几毫秒内完成。
11> v1 ! update. 
update code
update
12> v1 ! version.
version 2
version
13> v2 ! version.
version 2
version
14> whereis(v1).   
<0.39.0>
15> whereis(v2). 
<0.50.0>
16> % modif version.
16> c(tver).        
{ok,tver}
17> whereis(v1).    
<0.39.0>
18> whereis(v2).    
<0.50.0>
19> v1 ! version.   
version 2
version
20> v1 ! version.   
version 2
version
21> v2 ! version.   
version 2
version
22> tver:start(v3). 
true
23> v2 ! version.  
version
version 2
24> v3 ! version.
version 3
version
25> c(tver).                                                  
{ok,tver}
26> whereis(v1).                                              
undefined
27> whereis(v2).                                              
undefined
28> tver:start(v4).                                           
true
29> whereis(v3).                            
<0.69.0>
30> whereis(v4).
<0.80.0>
31> v3 ! version.                                             
version
version 3
32> v4 ! version.
version 4
version
33>