gpt4 book ai didi

elixir - Erlang/elixir : Difference between module redefine and hot code swap

转载 作者:行者123 更新时间:2023-12-02 08:29:41 25 4
gpt4 key购买 nike

代码交换:Achieving code swapping in Erlang's gen_server

模块重新定义:

iex(<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="6a04050e0f582a5b585d445a445a445b" rel="noreferrer noopener nofollow">[email protected]</a>)6> Code.load_file("mesngr.ex", "./lib")
[{Mesngr,
<<70, 79, 82, 49, 0, 0, 12, 72, 66, 69, 65, 77, 69, 120, 68, 99, 0, 0, 0, 255, 131, 104, 2, 100, 0, 14, 101, 108, 105, 120, 105, 114, 95, 100, 111, 99, 115, 95, 118, 49, 108, 0, 0, 0, 4, 104, 2, 100, 0, ...>>}]
iex(<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="76181912134436474441584658465847" rel="noreferrer noopener nofollow">[email protected]</a>)8> Code.load_file("mesngr.ex", "./lib")
lib/mesngr.ex:1: warning: redefining module Mesngr
[{Mesngr,
<<70, 79, 82, 49, 0, 0, 12, 72, 66, 69, 65, 77, 69, 120, 68, 99, 0, 0, 0, 255, 131, 104, 2, 100, 0, 14, 101, 108, 105, 120, 105, 114, 95, 100, 111, 99, 115, 95, 118, 49, 108, 0, 0, 0, 4, 104, 2, 100, 0, ...>>}]
iex(<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="dfb1b0bbbaed9feeede8f1eff1eff1ee" rel="noreferrer noopener nofollow">[email protected]</a>)9>

我已经注意到某些差异,例如在模块重新定义的情况下不会调用 GenServer 的 code_change 回调(因为我假设只是覆盖,而不是从新 -> 当前和当前 -> 旧的转换)。但我也注意到,像这样重新定义模块确实会改变底层代码(这在 FP 语言中是有意义的)。

我想我的问题可以归结为以下几点:

  1. 在开发和生产过程中简单地动态重新定义模块会有多好/坏/丑陋?
  2. 除了版本管理和回滚之外,进行正确的代码交换有哪些好处?有关于该主题的好的教程/手册/文章吗?
  3. 与模块重新定义相比,热代码交换在幕后是如何工作的?

最佳答案

在 Erlang 中,在任何给定时间点,您最多可以有两个版本的给定模块主动运行。

示例:

  • 加载模块
  • 使用代码启动 gen_server
  • 更改某些内容并加载模块' - 现在 gen_server 仍在运行旧代码
  • 启动第二个 gen_server - 它将运行模块中的新代码
  • 再次更改某些内容并加载模块'' - 因为同一代码在任何时间点只能有两个版本,所以第一个模块将被清除;所有运行它的进程都被杀死,所以你的第一个 gen_server 被杀死

您可以通过从该模块调用完全限定的函数来从运行旧代码转换为在进程内运行新代码。因此,您不必调用 function(Args),而是执行 module:function(Args)。我不确定同样的机制是否适用于 Elixir。

要手动进行热代码升级,您必须在第一个版本的模块中调用此完全限定的函数。

如果您更改了 gen_server 中的状态表示,这可能会使服务器崩溃。

回答你的问题:

  1. 这将是非常糟糕的。手动执行此操作意味着仅对升级进行手动测试。它可能导致随机进程死亡、丢失状态,在极端情况下还会丢失数据。

  2. 与 appups 和 relups 的热代码交换是完全自动化的。您不需要像第一个代码版本中的完全限定函数那样的“ Hook ”,因此当您需要进行热代码升级时,您可以开始担心它。代码更改将被正确调用,让您有机会将旧状态转换为新状态。如果您修改多个进程,您可以定义在升级过程中应卡住的一组模块。我认为这里有一个很好的教程:http://learnyousomeerlang.com/relups

  3. 热代码交换刚刚开始通过使用先前模块定义的进程来使用新模块定义。进行正确的 appup 和 relup 处理代码加载、交换、更改状态和清除旧内容。使其更易于测试。

热代码交换并不容易,并且在生产中当您拥有分布式系统时,最好使用新代码启动全新的实例。负载均衡器可以将新连接推送到新实例,我们只需等待旧连接消失,然后再杀死旧实例。

但是,在只有一个实例并需要在线 24/7 热代码交换的嵌入式系统中,这可能是唯一的选择。

关于elixir - Erlang/elixir : Difference between module redefine and hot code swap,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36172340/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com