如何让Elixir节点在启动时自动连接? [英] How to get elixir nodes to connect automatically on startup?

查看:79
本文介绍了如何让Elixir节点在启动时自动连接?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在几个灵丹妙药节点之间设置群集。我的理解是,可以通过修改发行版vm.args进行设置。我正在使用Distillery构建发行版本,并在此处关注文档: https://hexdocs.pm /distillery/config/runtime.html

I'm trying to setup clustering between a few elixir nodes. My understanding is that I can set this up by modifying the release vm.args. I'm using Distillery to build releases and am following the documentation here: https://hexdocs.pm/distillery/config/runtime.html.

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

My rel/vm.args file is as follows:

-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服务器,然后将其取消存档并在此处启动。

I have a build server running Ubuntu 18.04 and two webservers running Ubuntu 18.04. I'm building the release on the build server, copying the archive to the webservers and, unarchiving it and starting it there.

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

On the server the two vm.args files are calculated to be:

-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使用以下配置运行发行版:

The releases are run via systemd with the following configuration:

[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()时,除非我手动连接两个节点,否则结果为空列表。

Problem

The releases start fine on both servers and but when I open a remote console and run Node.list() the result is an empty list unless I manually connect the two nodes.

如果我手动运行 Node.connect(: my_app@10.10.10.200)然后我会看到另一个每个节点上运行 Node.list()的节点,但这在启动时不会自动发生。

If I manually run Node.connect(:"my_app@10.10.10.200") I then see the other node when running Node.list() on each node, but this does not happen automatically on startup.

推荐答案

vm.args 文件以gett结尾使用 -args_file 参数传递给Erlang。我去看了 -args_file ,并且发现它实际上没有很好的记录。事实证明, vm.args 就像一个洋葱,因为它有很多层,文档似乎全部在源代码中。

The vm.args file ends up getting passed to Erlang using the -args_file argument. I went to look at the documentation for -args_file, and found that it's actually not very well documented. It turns out that vm.args is like an onion, in that it has lots of layers, and the documentation seems to be all in the source code.

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

Let's start with where we want to end up. We want sync_nodes_mandatory to be a list of atoms, and we need to write it in Erlang syntax. If we were using short node names, e.g. my_app@myhost, we could get away with not quoting the atoms, but atoms with dots in them need to be quoted using single quotes:

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

我们希望这是 erlexec.c 中的函数 build_args_from_string 。该函数有四个规则:

We want this to be the output of the function build_args_from_string in erlexec.c. This function has four rules:


  • 反斜杠字符转义任何一个字符

  • 双引号转义直到下一个双引号的所有字符(包括反斜杠)

  • 单引号将直到下一个双引号的所有字符(包括反斜杠)转义

  • 一个空格字符标记了参数的结尾

  • A backslash character escapes any one character
  • A double quote escapes all characters (including backslash) until the next double quote
  • A single quote escapes all characters (including backslash) until the next single quote
  • A space character marks the end of an argument

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

So since we want to pass the single quotes through to the parser, we have two alternatives. We can escape the single quotes:

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

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

Or we can enclose the single quotes in double quotes:

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

(实际上,只要每次出现单引号都在双引号内,我们将双引号放在多少和位置都没有关系

(In fact, it doesn't matter how many and where we put the double quotes, as long as every occurrence of a single quote is inside a pair of double quotes. This is just one possible way of doing it.)

BUT 如果我们选择用反斜杠转义单引号,我们遇到另一层! 函数 read_args_file 是实际上从磁盘读取 vm.args 文件的函数,然后将其传递给 build_args_from_string ,并且它首先施加自己的规则!即:

BUT if we choose to escape the single quotes with backslashes, we encounter another layer! The function read_args_file is the function that actually reads the vm.args file from disk before passing it to build_args_from_string, and it imposes its own rules first! Namely:


  • 反斜杠字符转义任何一个字符

  • A 字符将忽略所有字符,直到下一个换行符为止。

  • 除非用反斜杠转义,否则任何空格字符都将替换为一个空格

  • A backslash character escapes any one character
  • A # character ignores all characters until the next newline
  • Any whitespace character is replaced by a single space, unless escaped by a backslash

因此,如果我们要写 [\'my_app @ 10.10.10.100\',\'my_app @ 10.10.10.200\' ] vm.args read_args_file 中会吃反斜杠,而 build_args_from_string 会吃掉单引号,给我们留下一个无效的术语和一个错误:

So if we were to write [\'my_app@10.10.10.100\',\'my_app@10.10.10.200\'] in vm.args, read_args_file would eat the backslashes, and build_args_from_string would eat the single quotes, leaving us with an invalid term and an error:

$ 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

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

So we could either use double backslashes:

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

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

Or just stick with double quotes (a different, equally valid, variant this time):

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

内核应用程序,还需要将 sync_nodes_timeout 设置为以毫秒为单位的时间或无限

As noted in the documentation for the kernel application, you also need to set sync_nodes_timeout to a time in milliseconds or 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

这篇关于如何让Elixir节点在启动时自动连接?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆