我正在尝试在几个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()
时会看到另一个节点,但这不会在启动时自动发生。
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.args
写read_args_file
,build_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
这是另一种解决方案。我在调查这个问题时找到了它。
使用以下内容创建文件[{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进行验证。
现在,您可以考虑在构建版本时生成此配置文件。