在Erlang的gen_server中实现代码交换
我希望在 gen_server 上利用 Erlang 的热代码交换功能,这样我就不必重新启动它。我该怎么做呢?当我搜索时,我只能找到一篇文章提到我需要使用 gen_server:code_change
回调。
但是,我确实找不到任何有关如何使用它的文档/示例。非常感谢任何帮助或资源链接!
I am looking to make use of Erlang's hot code swapping feature on a gen_server, so that I don't have to restart it. How should I do that? When I searched, all I could find was one article which mentioned that I need to make use of gen_server:code_change
callback.
However, I could not really find any documentation/examples on how to use this. Any help or links to resources greatly appreciated!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
正如我已经提到的,正常的升级方法是创建正确的 .appup 和 .relup 文件,并让 release_handler 执行需要执行的操作。但是,您可以手动执行所涉及的步骤,如此处所述。抱歉回答太长。
下面的虚拟 gen_server 实现了一个计数器。旧版本(“0”)仅将整数存储为状态,而新版本(“1”)将 {tschak, Int} 存储为状态。正如我所说,这是一个虚拟示例。
z.erl(旧):
z.erl(新):
启动 shell,并编译旧代码。请注意,gen_server 是通过调试跟踪启动的。
按预期工作:返回 Int,新状态为 Int+1。
现在将 z.erl 替换为新的 z.erl,并执行以下步骤。
您刚刚做了什么: 5:编译新代码。 6:暂停服务器。 7:清除旧代码(以防万一)。 8:加载新代码。 9:在模块“z”的进程“z”中从版本“0”调用代码更改,并将 [] 作为“Extra”传递给 code_change。 10:恢复服务器。
现在,如果您运行更多测试,您可以看到服务器使用新的状态格式:
As I already mentioned the normal way of upgrading is creating the proper .appup and .relup files, and let release_handler do what needs to be done. However you can manually execute the steps involved, as described here. Sorry for the long answer.
The following dummy gen_server implements a counter. The old version ("0") simply stores an integer as state, while the new version ("1") stores {tschak, Int} as state. As I said, this is a dummy example.
z.erl (old):
z.erl (new):
Start the shell, and compile the old code. Notice the gen_server is started with debug trace.
Works as expected: returns the Int, and new state is Int+1.
Now replace z.erl with the new one, and execute the following steps.
What you just did: 5: compiled the new code. 6: suspended the server. 7: purged older code (just in case). 8: loaded the new code. 9: invoked code change in process 'z' for module 'z' from version "0" with [] passed as "Extra" to code_change. 10: resumed the server.
Now if you run some more tests, you can see, that the server works with the new state format:
您不需要在
gen_server
行为中使用该回调。如果您通过代码升级更改状态的内部表示,它就在那里。您只需要加载新模块,运行旧版本的
gen_server
就会升级,因为它调用新模块。只是如果有必要,您没有机会更改表示形式。You don't need to use that callback in the
gen_server
behaviour. It is there if you change the internal representation of the state across a code upgrade.You only need to load the new module and the
gen_server
running the old version will upgrade, since it calls the new module. It is just that you dont have a chance to change the representation if that is necessary.最简单的方法是替换
.beam
文件并在 shell 中运行l(my_server_module).
。这绕过了code_change函数,因此要求状态的表示没有改变。如前所述,正确的方法是使用 appup 和 relup 脚本创建新版本。然后,这个新版本将与 release_handler 一起安装。
The simplest way to do it is replace the
.beam
file and runl(my_server_module).
in the shell. This bypasses thecode_change
function, and therefore requires that the representation of state hasn't changed.As mentioned already, the proper way to do it is to create a new release with appup and relup scripts. This new release is then installed with release_handler.
如果您想以正确的方式进行操作(强烈建议这样做),那么您需要阅读 OTP 管理程序和应用程序的使用。
您可能会比在这里阅读《OTP 设计原则用户指南》更糟糕:
http://www .erlang.org/doc/design_principles/users_guide.html
If you want to do it the right way, which is highly recommended, then you need to read up on the use of OTP Supervisors and Applications.
You could do worse than to read the OTP Design Principles User's Guide here :
http://www.erlang.org/doc/design_principles/users_guide.html
如果您使用 rebar3,部分手动处理已被自动化(即 appup 和 relup 生成),您可以在此处找到更多信息:http://lrascao.github.io/automatic-release-upgrades-in-erlang/
If you're on rebar3, some of this manual processing has been automated away (ie. appup and relup generation), you can find more info here: http://lrascao.github.io/automatic-release-upgrades-in-erlang/