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

时间:2019-04-25 02:27:13

标签: erlang elixir distillery

背景

我正在尝试在一些长生不老药节点之间设置群集。我的理解是,可以通过修改发行版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 hifyre_platform@10.10.10.100
-setcookie wefijow89236wj289*PFJ#(*98j3fj()#J()#niof2jio
-smp auto
-kernel inet_dist_listen_min 9100 inet_dist_listen_max 9155
-kernel sync_nodes_mandatory '["\'my_app@10.10.10.100\'","\'my_app@10.10.10.200\'"]'

-name hifyre_platform@10.10.10.200
-setcookie wefijow89236wj289*PFJ#(*98j3fj()#J()#niof2jio
-smp auto
-kernel inet_dist_listen_min 9100 inet_dist_listen_max 9155
-kernel sync_nodes_mandatory '["\'my_app@10.10.10.100\'","\'my_app@10.10.10.200\'"]'

这些发布是通过具有以下配置的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(:"my_app@10.10.10.200"),则在每个节点上运行Node.list()时都会看到另一个节点,但这在启动时不会自动发生。

2 个答案:

答案 0 :(得分:3)

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

让我们从我们要结束的地方开始。我们希望sync_nodes_mandatory是原子列表,并且需要用Erlang语法编写。如果我们使用短节点名称,例如my_app@myhost,我们可以避免不引用原子,但是其中带有点的原子需要使用单引号引起来:

['my_app@10.10.10.100','my_app@10.10.10.200']

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

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

因此,由于我们要将单引号传递给解析器,因此有两种选择。我们可以转义单引号:

[\'my_app@10.10.10.100\',\'my_app@10.10.10.200\']

或者我们可以将单引号括在双引号中:

["'my_app@10.10.10.100','my_app@10.10.10.200'"]

(实际上,只要将单引号的每次出现都放在一对双引号之内,我们放置双引号的数量和位置并不重要。这只是一种可行的实现方式。)

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

  • 反斜杠字符转义任何一个字符
  • [\'my_app@10.10.10.100\',\'my_app@10.10.10.200\']字符会忽略所有字符,直到下一个换行符为止
  • 除非用反斜杠转义,否则任何空格字符都将替换为一个空格

因此,如果我们要在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: ","'.'"] "[my_app@10.10.10.100,my_app@10.10.10.200]" {"could not start kernel pid",application_controller,"{bad_environment_value,\"[my_app@10.10.10.100,my_app@10.10.10.200]\"}"} could not start kernel pid (application_controller) ({bad_environment_value,"[my_app@10.10.10.100,my_app@10.10.10.200]"}) Crash dump is being written to: erl_crash.dump...done 将使用单引号,从而给我们留下无效的条件,并且错误:

-kernel sync_nodes_mandatory [\\'my_app@10.10.10.100\\',\\'my_app@10.10.10.200\\']

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

-kernel sync_nodes_mandatory "['my_app@10.10.10.100','my_app@10.10.10.200']"

或者只用双引号(这次是不同的,同样有效的变体):

sync_nodes_timeout

the documentation for the kernel application中所述,您还需要将infinity设置为毫秒或-kernel sync_nodes_timeout 10000 的时间:

  

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

添加类似内容:

``class ElementPosPayment : FormElement, ValueFormElement, 
      ReadyFormElement, ApiDataView, View.OnClickListener {

//Error occurs here on both value and activity variables declarations
private var value: String? = null 
private var activity: BaseActivity? = null 




//The interface class for ValueFormElement is
interface ValueFormElement : BaseElement {

var value: Pair<Boolean, Hashtable<String, String>>
var name: String
fun setValue(value: String)

}

答案 1 :(得分:1)

这是另一种解决方案。我在调查此问题时发现了它。

创建具有以下内容的文件./priv/sync.config

[{kernel, [
  {sync_nodes_mandatory, ['my_app@10.10.10.200', 'my_app@10.10.10.200']},
  {sync_nodes_timeout, 15000}
]}].

将此行添加到vm.args

-config <%= :code.priv_dir(release_name) %>/sync

构建一个发行版,并在15秒钟(配置文件中的超时值)内连接控制台,并启动两个节点。执行Node.list()进行验证。

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