Brincando com Erlang nodes: epmd
- 3 minutes read - 623 wordsEste post faz parte de uma série de outros posts relacionados a como usar Erlang distribution protocol.
Na primeira parte, Brincando com Erlang nodes: eclero , criamos uma aplicação básica. Já na segunda parte, Brincando com Erlang nodes: embedded , colocamos a aplicação em uma imagem Linux. Agora, o próximo passo é falar sobre o epmd.
Mas antes vamos atualizar a lista dos requisitos:
Cada nó necessita detectar e ser notificado de qualquer falha dos outros nós- O cluster de nós Erlang deve ser configurado utilizando algum tipo de configuração vinda do ambiente
O ambiente de execução é Linux embarcado rodando em qualquer plataformaDesejável poder rodar em um ambiente embarcado com o mínimo de recursos necessários- Mínimo de 3 nós para a solução funcionar
epmd
epmd: Erlang Portmap Daemon é um
daemon no qual conhece o endereço e nomes de todos os nós Erlang de dentro de um
cluster. Geralmente é inicializado junto com o nó ou quando executamos o comando
erl
. Mas pode ser configurado para inicilizar independente se a VM Erlang foi
iniciada ou não. Vale mencionar que o epmd possui integração com systemd e os
logs podem ser enviados para o syslog.
O problema
No caso eclero embedded, o daemon epmd não é inicializado quando o nó erlang é ativado. Por dois motivos:
- Falta de suporte por parte da distribuição Linux que fizemos (não instalei os pacotes necessários)
- erlinit utiliza uma outra estratégia para iniciar o nó erlang, fazendo com que o epmd não seja inicializado adequadamente pela VM Erlang.
Mas, será que realmente o epmd é necessário ? Dependendo do contexto, não.
Para resolver o problema, poderia:
- utilizar a opção descrita aqui: Support launching epmd -daemon
- seguir esta documentação (na qual parece obsoleta, mas iria funcionar) Add an Erlang distribution how-to
- instalar os pacotes principais do Erlang e também mais pacotes bases para a distribuição ter um melhor suporte e por fim executar o epmd
- abandonar o erlinit, desistir de fazer com que a aplicação execute em um ambiente embarcado e restritivo
Entretanto a opção escolhida foi não utilizar o epmd.
A solução
Na release 19 do Erlang, foi adicionado suporte para desativar o epmd ou substituir por outra implementação. Então ao longo do tempo foi surgindo diversas alternativas:
- Erlang Port Mapper Daemon escrito em Erlang
- Erlang (and Elixir) distribution without epmd, aka EPMDLESS
Também foi documentado como escrever um epmd alternativo:
Bem como opções de linha de comando para executarmos a Erlang VM sem epmd:
- http://erlang.org/doc/man/erl.html
-start_epmd true | false
-epmd_module Module (init flag)
-proto_dist Proto
A alternativa mais viável foi utilizar a biblioteca epmdless. Sendo assim, na aplicação eclero foi necessário duas alterações:
- incluir epmdless como dependência no arquivo rebar.config
1 {eunit, "-c"},
2 {ct, "-c"},
3 {cover, "-v --min_coverage=80"}]}
4]}.
- criar uma configuração mínima para o nó ser inicializado com as opções corretas da VM Erlang, no arquivo vm.config
1-proto_dist epmdless_proto
2
3-start_epmd false
4
5-epmd_module epmdless_client
- adicionar a configuração necessária para a aplicação epmdless no arquivo sys.config
1 {epmdless, [
2 {transport, tcp},
3 {listen_port, 17012}
4 ]}
Feito isso, fazendo os procedimentos de build e testes, podemos verificar que o ambiente está operacional e usando a biblioteca epmdless:
checando se os argumentos foram passados corretamente para a VM:
1 (eclero1@eclero)1> 2init:get_argument(start_epmd). {ok,[["false"]]} (eclero1@eclero)2> 3init:get_argument(proto_dist). {ok,[["epmdless_proto"]]} (eclero1@eclero)3> 4init:get_argument(epmd_module). {ok,[["epmdless_client"]]}
verificando se a VM está usando um epmd alternativo:
1 (eclero1@eclero)4> 2net_kernel:epmd_module(). epmdless_client (eclero1@eclero)5> 3 4(eclero1@eclero)6> net_adm:ping(node()). pong 5 6(eclero1@eclero)7> erlang:node(). eclero1@eclero
Conclusão
Como vimos, existem motivos e alternativas para utilizar outra implementação do epmd. Dependendo do seu projeto isso pode ser bastante útil. Como por exemplo descobrir outros nós em um cluster de forma determinística, no qual vamos abordar no próximo post Brincando com Erlang nodes: cloonix