Docker 上的 Erlang/Elixir 和热代码交换

Posted

技术标签:

【中文标题】Docker 上的 Erlang/Elixir 和热代码交换【英文标题】:Erlang/Elixir on Docker and Hot Code Swap 【发布时间】:2016-07-10 11:21:21 【问题描述】:

Erlang(根据定义,也就是 Elixir)的特性之一是您可以进行代码热交换。但是,这似乎与 Docker 不一致,您需要停止实例并使用包含新代码的新映像重新启动新实例。这基本上似乎是每个人都在做的事情。

话虽如此,我也知道可以使用一个隐藏节点通过网络将更新分发给所有其他节点。当然,这样听起来像是自找麻烦,但是……

我的问题如下:有没有人尝试过为 Erlang/Elixir 建立一个允许热代码交换的基于 Docker 的基础架构并取得了相当大的成功?如果是,有哪些注意事项、注意事项和注意事项?

【问题讨论】:

尽管我发表了评论,但我相信这还没有真正得到回答。我相信可以写更多关于在 Docker 中使用 HCS 的不同实现策略。我的猜测是,只要您保持 PROD 与 HEAD 对齐,Docker 与否无关紧要,新容器是否通过 Docker 或 Erlang 推送都无关紧要。但一定要保持同步! Docker 并不是特别适合 Erlang —— 它只是部署当今许多年轻商店所知道的任何东西的唯一方法。大多数人试图用 Docker 解决的问题(轻量级并行性、执行环境卫生、“网络就是抽象”、进程隔离、内存安全等)是 Erlang 已经以更完整的方式解决的问题。热代码升级需要对运动中的数据类型和运行时的存储/代码加载环境有高度的控制和知识。 Docker在正常情况下阻止了第二个要求。 @zxq9:这让我更有信心在 Docker 之外运行 Phoenix/Elixir 应用程序,但是 HCS 在使用 CircleCI 或 TravisCI 的 DevOps 环境中真的有意义吗?从根本上说,Erlang HCS 与 Docker 和 CI 工具不正交吗?这需要重新评估 HCS 功能,我们知道 PaaS 通常不允许节点以 HCS 需要正常工作的方式相互交互。这应该是一个全新的帖子:Erlang Web 应用程序是否应该牺牲 HCS 来支持 Docker 和 CI? @Aki CI 工具与 Docker 类似:它们解决了 Erlang 已经以不同方式解决的问题。我想有人可以强迫 Travis 与 HCS 集成,但我不知道为什么这会是可取的。例外情况(普遍适用于 Docker、临时 VM 实例 CI 工具)是为 Erlang 代码使用外部远程代码服务器。这意味着,您的所有实例(或其他)都不是从本地系统加载代码,而是从远程代码服务器作为预编译的二进制文件动态加载(这也是引入 *.ez 压缩二进制文件的部分原因)。 @Aki 我现在没有时间做[1],但我很想写一篇关于使用几乎空的运行时和远程代码服务器的操作指南——也许这个这将是解决年轻和天真的 DevOps 员工圈子的方法,他们除了 github 集成的 CI 工具 + Docker 进行部署之外一无所知。 ([1] 没有人付钱给我,也没有人愿意付钱给我,而且我已经将我所有的未付时间用于创建冗余的对等分布式源包 repo 系统 + 用于按需编译 + 运行功能的相关工具。它可能适用不过,更多的是客户端而不是后端。) 【参考方案1】:

故事

想象一个系统来处理手机通话或移动数据访问(这就是创建 Erlang 的目的)。有网关服务器在通话期间维护用户会话,或数据访问会话(我将其称为向前的会话)。只要会话处于活动状态(用户已连接),这些服务器就会在内存中表示会话。

现在有另一个系统可以计算向用户收取的通话费用或传输数据的费用(称为 PDF - Policy Decision Function)。两个系统的连接方式是网关服务器创建少量到 PDF 的 TCP 连接,如果这些 TCP 连接断开,它会丢弃用户会话。网关一次可以处理几十万客户。每当发生需要向用户收费的事件(下一次数据传输,另一分钟的通话)时,网关都会通知 PDF 该事实,并且 PDF 从用户帐户中减去特定金额。当用户帐号为空时PDF通知网关断开通话(你的钱用完了,你需要充值)。

您的问题

最后让我们在这个背景下谈谈你的问题。我们要升级一个 PDF 节点并且该节点正在 Docker 上运行。我们用新版本的软件创建了一个新的 Docker 实例,但是我们不能关闭旧版本(有成千上万的客户在他们的通话中,我们不能断开他们的连接)。但是我们需要以某种方式将客户从旧 PDF 转移到新版本。因此,我们告诉网关节点创建与更新节点而不是旧 PDF 的任何新连接。客户可能很健谈,而且他们中的一些人可能有长时间运行的数据连接(下载 Windows 10 iso),因此整个操作需要 2-3 天才能完成。这是在出现严重错误时将软件的一个版本升级到另一个版本所需的时间。像这样的服务器可能有几十台,每台都处理数十万客户。

但是如果我们使用 Erlang 发布处理程序来代替呢?我们使用新版本的软件创建 relup 文件。我们对其进行正确测试并部署到 PDF 节点。每个节点都在原地升级——应用程序的内部状态被转换,节点正在运行新版本的软件。但最重要的是,与网关服务器的 TCP 连接并没有断开。因此,在我们升级系统的同时,客户可以愉快地继续通话或下载最新的 Windows iso。全部在 10 秒内完成,而不是 2-3 天。

答案

这是具有特定要求的特定系统的示例。 Docker 和Erlang's Release Handling 是正交技术。您可以使用其中一个或两个,归结为以下几点:

要求 成本

您是否有足够的资源以可预测的方式测试这两种方法,并有足够的耐心来教导您的 Ops 团队,以便他们可以使用任何一种方法部署系统?如果测试设施耗资数百万英镑(因为需要硬件)并且一次只能使用这两种方法中的一种(因为测试周期需要几天时间)怎么办?

务实的方法可能是最初使用 Docker 部署节点,然后使用 Erlang release handler 升级它们(如果您首先需要使用 Docker)。或者,如果您的系统在升级期间不需要可用(如示例 PDF 系统所做的那样),您可能只是选择始终使用 Docker 部署新版本而忘记发布处理。或者,如果您需要快速可靠的即时更新并且 Docker 仅用于初始部署,您也可以坚持使用发布处理程序并忘记 Docker。我希望这会有所帮助。

【讨论】:

好答案,关于这个主题的文献很少,这是对我的主要参考之一。似乎 Docker 无处不在,大多数 CI 工具和云提供商都在迎合它,我想说现在使用 Docker 对于大多数应用程序来说是一件轻而易举的事。但是热代码交换功能非常有用,我建议每个人都尝试一下,并利用此功能实施计划外紧急更改的程序。 谢谢@Aki 每个主题都有很多文献。很少有文献讨论这两者,因为它们真的不需要一起讨论。无论 Erlang 应用程序是使用 Docker 还是使用任何其他技术部署的,您都可以使用 HCS。

以上是关于Docker 上的 Erlang/Elixir 和热代码交换的主要内容,如果未能解决你的问题,请参考以下文章

如何在服务器上正确安装 Erlang、Elixir 和 mix?

Erlang - Elixir:啥是监督树?

Elixir/Erlang 中的命名函数是不是有等效于 __MODULE__ 的方法?

Erlang/Elixir精选-第1期

如何从 Erlang/Elixir 中的 ets 集中选择一个随机元素?

Erlang/Elixir精选-第6期(20200113)