如何在启动时自动连接elixir节点?

问题描述 投票:2回答:2

背景

我正在尝试在几个elixir节点之间设置群集。我的理解是我可以通过修改发布vm.args来设置它。我正在使用Distillery构建版本,并遵循以下文档:https://hexdocs.pm/distillery/config/runtime.html

我的rel / vm.args文件如下:

-name <%= release_name %>@${HOSTNAME}
-setcookie <%= release.profile.cookie %>
-smp auto
-kernel inet_dist_listen_min 9100 inet_dist_listen_max 9155
-kernel sync_nodes_mandatory '[${SYNC_NODES_MANDATORY}]'

我有一个运行Ubuntu 18.04的构建服务器和两个运行Ubuntu 18.04的Web服务器。我正在构建服务器上构建版本,将存档复制到Web服务器,然后取消存档并在那里启动它。

在服务器上,两个vm.args文件计算为:

-name [email protected]
-setcookie wefijow89236wj289*PFJ#(*98j3fj()#J()#niof2jio
-smp auto
-kernel inet_dist_listen_min 9100 inet_dist_listen_max 9155
-kernel sync_nodes_mandatory '["\'[email protected]\'","\'[email protected]\'"]'

-name [email protected]
-setcookie wefijow89236wj289*PFJ#(*98j3fj()#J()#niof2jio
-smp auto
-kernel inet_dist_listen_min 9100 inet_dist_listen_max 9155
-kernel sync_nodes_mandatory '["\'[email protected]\'","\'[email protected]\'"]'

这些版本通过systemd运行,具有以下配置:

[Unit]
Description=My App
After=network.target

[Service]
Type=simple
User=ubuntu
Group=ubuntu
WorkingDirectory=/opt/app
ExecStart=/opt/app/bin/my_app foreground
Restart=on-failure
RestartSec=5
Environment=PORT=8080
Environment=LANG=en_US.UTF-8
Environment=REPLACE_OS_VARS=true
Environment=HOSTNAME=10.10.10.100
SyslogIdentifier=my_app
RemainAfterExit=no

[Install]
WantedBy=multi-user.target

问题

两个服务器上的发布都很好,但是当我打开一个远程控制台并运行Node.list()时,结果是一个空列表,除非我手动连接这两个节点。

如果我手动运行Node.connect(:"[email protected]"),那么在每个节点上运行Node.list()时会看到另一个节点,但这不会在启动时自动发生。

erlang elixir distillery
2个回答
3
投票

vm.args文件最终使用-args_file参数传递给Erlang。我去看了the documentation for -args_file,发现它实际上没有很好的记录。事实证明,vm.args就像一个洋葱,因为它有很多层,文档似乎都在源代码中。

让我们从我们想要结束的地方开始吧。我们希望sync_nodes_mandatory是一个原子列表,我们需要用Erlang语法编写它。如果我们使用短节点名称,例如my_app@myhost,我们可以不引用原子而离开,但是带有点的原子需要使用单引号引用:

['[email protected]','[email protected]']

我们希望这是the function build_args_from_string in erlexec.c的输出。此功能有四个规则:

  • 反斜杠字符会转义任何一个字符
  • 双引号会转义所有字符(包括反斜杠)直到下一个双引号
  • 单引号将转义所有字符(包括反斜杠)直到下一个单引号
  • 空格字符标志着参数的结束

因此,由于我们希望将单引号传递给解析器,因此我们有两种选择。我们可以逃避单引号:

[\'[email protected]\',\'[email protected]\']

或者我们可以用双引号括起单引号:

["'[email protected]','[email protected]'"]

(事实上​​,只要单引号的每一次出现都在一对双引号内,这与我们放双引号的数量和位置并不重要。这只是一种可能的方法。)

但是如果我们选择使用反斜杠转义单引号,我们会遇到另一层! The function read_args_file是在将vm.args文件传递给build_args_from_string之前从磁盘读取#文件的函数,它首先强加了自己的规则!即:

  • 反斜杠字符会转义任何一个字符
  • 在下一个换行符之前,[\'[email protected]\',\'[email protected]\']字符会忽略所有字符
  • 除非通过反斜杠转义,否则任何空白字符都将替换为单个空格

因此,如果我们在vm.argsread_args_filebuild_args_from_string会吃掉反斜杠,而$ iex --erl '-args_file /tmp/vm.args' 2019-04-25 17:00:02.966277 application_controller: ~ts: ~ts~n ["syntax error before: ","'.'"] "[[email protected],[email protected]]" {"could not start kernel pid",application_controller,"{bad_environment_value,\"[[email protected],[email protected]]\"}"} could not start kernel pid (application_controller) ({bad_environment_value,"[[email protected],[email protected]]"}) Crash dump is being written to: erl_crash.dump...done 会吃单引号,留下一个无效的术语和错误:

-kernel sync_nodes_mandatory [\\'[email protected]\\',\\'[email protected]\\']

所以我们可以使用双反斜杠:

-kernel sync_nodes_mandatory "['[email protected]','[email protected]']"

或者只是坚持使用双引号(这次是另一种同样有效的变体):

the documentation for the kernel application

sync_nodes_timeout所述,您还需要将infinity设置为以毫秒为单位的时间或-kernel sync_nodes_timeout 10000

指定此节点等待强制节点和可选节点启动的时间(以毫秒为单位)。如果未定义此参数,则不执行节点同步。

添加如下内容:

./priv/sync.config

1
投票

这是另一种解决方案。我在调查这个问题时找到了它。

使用以下内容创建文件[{kernel, [ {sync_nodes_mandatory, ['[email protected]', '[email protected]']}, {sync_nodes_timeout, 15000} ]}].

vm.args

将此行添加到-config <%= :code.priv_dir(release_name) %>/sync

Node.list()

构建一个版本并在15秒内启动两个节点(配置文件中的超时值)并附带控制台。执行qazxswpoi进行验证。

现在,您可以考虑在构建版本时生成此配置文件。

© www.soinside.com 2019 - 2024. All rights reserved.