gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-04 02:49:01 25 4
gpt4 key购买 nike

背景

我正在尝试在几个 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 的网络服务器。我在构建服务器上构建版本,将存档复制到网络服务器,然后取消存档并在那里启动它。

在服务器上,两个 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() 时我会看到另一个节点,但这不会在启动时自动发生。

最佳答案

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 之前实际从磁盘读取文件的函数,它首先施加了自己的规则!即:

  • 反斜杠字符转义任何一个字符
  • # 字符忽略所有字符,直到下一个换行符
  • 任何空白字符都被一个空格替换,除非用反斜杠转义

因此,如果我们要在 vm.args 中编写 [\'my_app@10.10.10.100\',\'my_app@10.10.10.200\']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']"

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

Specifies the time (in milliseconds) that this node waits for the mandatory and optional nodes to start. If this parameter is undefined, no node synchronization is performed.

添加如下内容:

-kernel sync_nodes_timeout 10000

关于erlang - 如何让 elixir 节点在启动时自动连接?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55840974/

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